Jerry's Blog

Recording what I learned everyday

View on GitHub


21 October 2019

LeetCode(44) -- 976, 977,

by Jerry Zhang

P976. Largest Perimeter Triangle (Easy)

一个整数数组,选三个数组成一个三角形。找出能形成周长最大的三个数。

我的思路

一开始用的暴力求解,n^3,超时了。

答案

先排序,然后从最大的三个数从后往前找。

public class E_976_LargestPerimeterTriangle {
    public int largestPerimeter(int[] A) {
        Arrays.sort(A);
        for (int i = A.length - 3; i >= 0; --i)
            if (A[i] + A[i+1] > A[i+2])
                return A[i] + A[i+1] + A[i+2];
        return 0;
    }
}

98%

最优解

class Solution {
    public int largestPerimeter(int[] A) {
        int max = getMax(A);
        int secondMax = getMax(A);
        int thirdMax = getMax(A);

        while(thirdMax != 0) {
            if(secondMax + thirdMax > max) {
                return secondMax + thirdMax + max;
            }
            max = secondMax;
            secondMax = thirdMax;
            thirdMax = getMax(A);
        }
        return 0;
    }

    public int getMax(int A[]) {
        int max = 0;
        int maxIndex = -1;
        for(int i = 0; i < A.length; i++) {
            if(A[i] > max) {
                max = A[i];
                maxIndex = i;
            }
        }

        if(maxIndex != -1) {
            A[maxIndex] = -1;
        }

        return max;

    }
}

遍历三次,找到前三大的数。每次找到最大数后,都把这个数改成-1,就不会影响后面再找了。如果最大的三个数不符合条件,就再找234大的数。因为2和3已经找到了,只需再从剩下的所有数里找一个最大的,也就是第四大的数即可。

P977. Squares of a Sorted Array (Easy)

给一个升序的整数数组,含负数。返回每个数的平方,同时还要求升序。

我的思路

绝对值最小的肯定要排第一位,所以第一个任务是找到数组中绝对值最小的,然后往两边扩散。

我的代码

public class E_977_SquaresofaSortedArray {
    public int[] sortedSquares(int[] A) {
        if (A.length == 2) {
            int[] ans = new int[2];
            if (Math.abs(A[0]) <= Math.abs(A[1])) {
                ans[0] = A[0] * A[0];
                ans[1] = A[1] * A[1];
                return ans;
            } else {
                ans[0] = A[1] * A[1];
                ans[1] = A[0] * A[0];
            }
        }
        int mid = smallestAbsoluteValue(A);
        List<Integer> ans = new ArrayList<>(A.length);
        ans.add(A[mid] * A[mid]);
        int l = mid - 1;
        int r = mid + 1;
        while (l >= 0 && r < A.length) {
            if (Math.abs(A[l]) < Math.abs(A[r])) {
                ans.add(A[l] * A[l]);
                l--;
            } else if (Math.abs(A[l]) > Math.abs(A[r])) {
                ans.add(A[r] * A[r]);
                r++;
            } else {
                int m = A[l] * A[l];
                ans.add(m);
                ans.add(m);
                l--;
                r++;
            }
        }
        while (l >= 0) {
            ans.add(A[l] * A[l]);
            l--;
        }
        while (r < A.length) {
            ans.add(A[r] * A[r]);
            r++;
        }
        return ans.stream().mapToInt(i->i).toArray();
    }

    private int smallestAbsoluteValue(int[] A) {
        if (A.length == 1) {
            return 0;
        }
        if (A[0] * A[A.length - 1] >= 0) {
            return (A[0] >= 0) ? 0 : A.length - 1;
        }
        int l = 0, r = A.length - 1, mid = 0;
        while (l <= r) {
            mid = l + (r - l) / 2;
            if (mid - 1 >= 0 && A[mid - 1] > 0) {
                r = mid - 1;
            } else if (mid + 1 < A.length && A[mid + 1] < 0) {
                l = mid + 1;
            } else {
                mid = (Math.abs(A[mid - 1]) < Math.abs(A[mid])) ? mid - 1 : mid;
                mid = (Math.abs(A[mid + 1]) < Math.abs(A[mid])) ? mid + 1 : mid;
                break;
            }
        }
        return mid;
    }
}

7%

最优解

class Solution {
    public int[] sortedSquares(int[] A) {
      if(A == null || A.length == 0) return new int[0];
      int[] answer = new int[A.length];
      int f = 0;
      int l = A.length - 1;
      int indx = answer.length -1;
      while(indx >= 0){
        int first = A[f] * A[f];
        int last = A[l] * A[l];
        answer[indx] = Math.max(first, last);
        if(first < last) l--;
        else f++;
        indx--;
      }
      return answer;
    }
}

为了找到绝对值最小的数,写binary search纠结了好久。其实完全可以从后往前做,从两侧用两个指针分别向中间移动。

tags: LeetCode