Leetcode之數組(一)

目錄

1.best-time-to-buy-and-sell-stock

2.best-time-to-buy-and-sell-stock-ii

3.best-time-to-buy-and-sell-stock-iii

4.first-missing-positive

5.remove-duplicates-from-sorted-array

6.remove-duplicates-from-sorted-array-ii

7.merge-sorted-array

8.convert-sorted-array-to-binary-search-tree

9.two-sum

10.3sum

11.3sum-closest

12.4sum


1.best-time-to-buy-and-sell-stock

題目:假設你有一個數組,其中第i個元素是某隻股票在第i天的價格。如果你最多隻能完成一筆交易(即買一股和賣一股股票),設計一個算法來求最大利潤。

分析:見劍指offer面試題63 https://blog.csdn.net/Nibaby9/article/details/104126765

2.best-time-to-buy-and-sell-stock-ii

題目:假設你有一個數組,其中第i個元素表示某隻股票在第i天的價格。設計一個算法來尋找最大的利潤。你可以完成任意數量    的交易(例如,多次購買和出售股票的一股)。但是,你不能同時進行多個交易(即,你必須在再次購買之前賣出之前買的股票)。

分析:貪心法,相鄰兩天的股票價格只要是遞增,利潤就會加大。

   public int maxProfit(int[] prices) {
         if(prices == null || prices.length == 0)
            return 0;
        int max_profit = 0;
        for(int i = 1;i < prices.length;i++){
            if(prices[i] - prices[i-1] > 0)
                max_profit += prices[i] - prices[i-1];
        }
        return max_profit;
    }

3.best-time-to-buy-and-sell-stock-iii

題目:假設你有一個數組,其中第i個元素是某隻股票在第i天的價格。設計一個算法來求最大的利潤。你最多可以進行兩次交易。注意:你不能同時進行多個交易(即,你必須在再次購買之前出售之前買的股票)。

分析:貪心法。無論是買還是賣,模擬兩次買和賣,都取利潤的最大值即可。

 public int maxProfit(int[] prices) {
        if(prices == null || prices.length == 0)
            return 0;
        int buy1 = Integer.MIN_VALUE,sell1 = 0,buy2 = Integer.MIN_VALUE,sell2 = 0;
        for(int i = 0;i < prices.length;i++){
            buy1 = Math.max(buy1,-prices[i]);//第一次買股票的利潤
            sell1 = Math.max(sell1,prices[i] + buy1);//第一次賣股票後所盈利的
            buy2 = Math.max(buy2,sell1 - prices[i]);//第二次買股票後的利潤:第一次的利潤 - 股票錢
            sell2 = Math.max(sell2,prices[i] + buy2);
        }
        return sell2;
    }

4.first-missing-positive

題目:給出一個無序的整數型數組,求不在給定數組裏的最小的正整數。例如:給出的數組爲[1,2,0] 返回3,給出的數組爲[3,4,-1,1] 返回2.你需要給出時間複雜度在O(n)之內並且空間複雜度爲常數級的算法。

分析:數組下標從0開始,讓數組中滿足大於0和小於數組長度的數都滿足a[i]==i+1(注意:不能直接用A[i] != i+1來作爲循環條件,因爲有可能數組中根本i+1這個數),最後再遍歷數組第一個不滿足a[i]==i+1的就是缺失的最小正整數。

   public int firstMissingPositive(int[] A) {
        for(int i = 0;i < A.length;i++){
            while(A[i] > 0 && A[i] <= A.length && A[i] != A[A[i]-1]){
                int temp = A[A[i]-1];A[A[i]-1] = A[i];A[i] = temp;//swap(A[i],A[A[i]-1]);
            }
        }
        for(int i = 0;i < A.length;i++){
            if(A[i] != i+1)
                return i+1;
        }
        return A.length + 1;
    }

5.remove-duplicates-from-sorted-array

題目:給定一個已排序的數組,使用就地算法將重複的數字移除,使數組中的每個元素只出現一次,返回新數組的長度。不能爲數組分配額外的空間,你必須使用常熟級空間複雜度的就地算法。例如,給定輸入數組 A=[1,1,2],你給出的函數應該返回length=2,A數組現在是[1,2]。

分析:用len來標記數組當前加入非重複數字的有效長度即可。

   public int removeDuplicates(int[] A) {
        if(A.length == 0)
            return 0;
        int len = 0;
        for(int i = 1;i < A.length;i++){
            if(A[i] != A[i-1])
                A[++len] = A[i];
        }
        return len+1;
    }

6.remove-duplicates-from-sorted-array-ii

題目:繼續思考題目"Remove Duplicates":如果數組中元素最多允許重複兩次呢?例如:給出有序數組 A =[1,1,1,2,2,3],你給出的函數應該返回length =5,  A 變爲[1,1,2,2,3].

分析:在上題的基礎上,多加一個flag來標誌某元素重複的次數即可。

    public int removeDuplicates(int[] A) {
        if(A == null || A.length == 0)
            return 0;
        int len = 1,flag = 1;
        for(int i = 1;i < A.length;i++){
            if(A[i] != A[i-1]){
                A[len++] = A[i];
                flag = 1;
            }
            else if(flag == 1){
                    flag++;
                    A[len++] = A[i];
            }
        }
        return len;
    }

7.merge-sorted-array

題目:給出兩個有序的整數數組A和B,請將數組B合併到數組A中,變成一個有序的數組。注意:可以假設A數組有足夠的空間存放B數組的元素,A和B中初始的元素數目分別爲m和n

分析:將數從後往前依次放入即可。

    public void merge(int A[], int m, int B[], int n) {
        int i = m-1,j = n-1,x = m + n -1;
        while(i >= 0 && j >= 0){
            if(A[i] > B[j])
                A[x] = A[i--];
            else
                A[x] = B[j--];
            x--;
        }
        while(j >= 0)
            A[x--] = B[j--];
    }

8.convert-sorted-array-to-binary-search-tree

題目:給出一個升序排序的數組,將其轉化爲平衡二叉搜索樹(BST).

分析:找中間結點mid = (left + right)/2作爲根結點,遞歸求出左右子樹即可。出口易錯!!!

   public TreeNode sortedArrayToBST(int[] num) {
        if(num == null || num.length == 0)
            return null;
        return toBST(num,0,num.length);
    }

    private TreeNode toBST(int[] num, int left, int right) {
        if(left >= right ) //易錯
            return null;
        int mid = (left + right) / 2;
        TreeNode root = new TreeNode(num[mid]);
        root.left = toBST(num,left,mid);
        root.right = toBST(num,mid+1,right);
        return root;
    }

9.two-sum

題目:給出一個整數數組,請在數組中找出兩個加起來等於目標值的數,你給出的函數twoSum 需要返回這兩個數字的下標(index1,index2),需要滿足 index1 小於index2.。注意:下標是從1開始的,假設給出的數組中只存在唯一解。例如:給出的數組爲 {2, 7, 11, 15},目標值爲9,輸出 ndex1=1, index2=2。

分析:用HashMap來存儲每個數字的下標即可。

若數組已排好序,參見劍指offer面試題57 https://blog.csdn.net/Nibaby9/article/details/104126811

   public int[] twoSum(int[] numbers, int target) {
        int [] re = new int[2];
        HashMap<Integer,Integer> map = new HashMap<>();
        for(int i = 0;i < numbers.length;i++){
            if(map.containsKey(target - numbers[i])){
                re[0] = map.get(target - numbers[i]);
                re[1] = i + 1;
                return re;
            }
            else{
                map.put(numbers[i],i+1);
            }
        }
        return re;
    }

10.3sum

題目:給出一個有n個元素的數組S,S中是否有元素a,b,c滿足a+b+c=0?找出數組S中所有滿足條件的三元組。注意:三元組(a、b、c)中的元素必須按非降序排列。(即a≤b≤c);解集中不能包含重複的三元組。 例如,給定的數組 S = {-1 0 1 2 -1 -4},↵↵ 解集爲:↵ (-1, 0, 1)↵ (-1, -1, 2)

分析:先對數組排好序,然後固定第一個數字,就可以將問題轉化爲查找兩個數爲目標值。但是需特別注意去重問題!!!

   public ArrayList<ArrayList<Integer>> threeSum(int[] num) {
        ArrayList<ArrayList<Integer>> res = new ArrayList<>();
        if(num.length < 3)
            return res;
        Arrays.sort(num);
        for(int i = 0;i < num.length - 2;i++){
            if(num[i] + num[i+1] + num[i+2] > 0)
                return res;
            if(i > 0 && num[i] == num[i-1])
                continue;
            if(num[i] + num[num.length - 1] + num[num.length - 2] < 0)
                continue;
            int low = i + 1;
            int high = num.length - 1;
            while(low < high){
                if(num[i] + num[low] + num[high] == 0){
                    ArrayList<Integer> list = new ArrayList<>();
                    list.add(num[i]);list.add(num[low]);list.add(num[high]);
                    res.add(list);
                    low++;high--;
                    while(low < high && num[low] == num[low-1])
                        low++;
                    while(low < high && num[high] == num[high+1])
                        high--;
                }
                else if(num[i] + num[low] + num[high] > 0)
                    high--;
                else
                    low++;
            }
        }
        return res;
    }

11.3sum-closest

題目:給出含有n個整數的數組s,找出s中和加起來的和最接近給定的目標值的三個整數。返回這三個整數的和。你可以假設每個輸入都只有唯一解。 例如,給定的整數 S = {-1 2 1 -4}, 目標值 = 1.↵↵ 最接近目標值的和爲 2. (-1 + 2 + 1 = 2).

分析:跟上題思想一樣,只是在計算的過程中需記錄離目標值最接近的值。

     public int threeSumClosest(int[] num, int target){
        if(num.length < 3)
            return 0;
        Arrays.sort(num);
        int res = num[0] + num[1] + num[2];
        for(int i = 0;i < num.length - 2;i++){
            if(i > 0 && num[i] == num[i-1])
                continue;
            int low = i + 1;
            int high = num.length - 1;
            while(low < high){
                int sum = num[i] + num[low] + num[high];
                if(sum == target)
                    return target;
                else if(sum > target)
                    high--;
                else
                    low++;
                if(Math.abs(target - sum) < Math.abs(target - res))
                    res = sum;
            }
        }
        return res;
    }

12.4sum

題目:給出一個有n個元素的數組S,S中是否有元素a,b,c和d滿足a+b+c+d=目標值?找出數組S中所有滿足條件的四元組。注意:四元組(a、b、c、d)中的元素必須按非降序排列。(即a≤b≤c≤d);解集中不能包含重複的四元組。 例如:給出的數組 S = {1 0 -1 0 -2 2}, 目標值 = 0.↵↵ 給出的解集應該是:↵ (-1, 0, 0, 1)↵ (-2, -1, 1, 2)↵ (-2, 0, 0, 2)

分析:固定一個數,就可把問題轉換爲滿足目標值得三元組。

   public ArrayList<ArrayList<Integer>> fourSum(int[] num, int target) {
        ArrayList<ArrayList<Integer>> res = new ArrayList<>();
        if(num.length < 4)
            return res;
        Arrays.sort(num);
        for(int i = 0;i < num.length - 3;i++){
            if(num[i] + num[i+1] + num[i+2] + num[i+3] > target)
                return res;
            if(i > 0 && num[i] == num[i-1])
                continue;
            if(num[i] + num[num.length - 1] + num[num.length - 2] + num[num.length - 3] < target)
                continue;
            for(int j = i + 1;j < num.length - 2;j++){
                if(num[i] + num[j] + num[j+1] + num[j+2] > target)
                    break;
                if(j > i + 1 && num[j] == num[j-1])
                    continue;
                if(num[i] + num[j] + num[num.length - 1] + num[num.length - 2] < target)
                    continue;
                int low = j + 1;
                int high = num.length - 1;
                while(low < high){
                    if(num[i] + num[j] + num[low] + num[high] == target){
                        ArrayList<Integer> list = new ArrayList<>();
                        list.add(num[i]);list.add(num[j]);list.add(num[low]);list.add(num[high]);
                        res.add(list);
                        low++;high--;
                        while(low < high && num[low] == num[low-1])
                            low++;
                        while(low < high && num[high] == num[high+1])
                            high--;
                    }
                    else if(num[i] + num[j] + num[low] + num[high] > target)
                        high--;
                    else
                        low++;
                }
            }
        }
        return res;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章