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;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章