Jerry's Blog

Recording what I learned everyday

View on GitHub


26 October 2019

LeetCode(49) -- 1013, 1018, 1021, 1022, 1029

by Jerry Zhang

P1013. Partition Array Into Three Parts With Equal Sum (Easy)

一个整数数组,问能否分成三份,使每一部分的和都相等。

我的思路

先把总和求出来,然后算出来1/3。然后依次遍历,看是否是出现三次这个目标值(总和的1/3)

我的代码

class Solution {
    public boolean canThreePartsEqualSum(int[] A) {
        int sum = 0;
        for (int i : A) {
            sum += i;
        }
        if (sum % 3 != 0) {
            return false;
        }
        int oneThird = sum / 3;
        int sum2 = 0;
        int i = 0;
        for (int j = 0; j < 2; j++) {
            while (i < A.length && sum2 != oneThird) {
                sum2 += A[i];
                i++;
            }
            if (i == A.length) {
                return false;
            }
            sum2 = 0;
        }
        while (i < A.length) {
            sum2 += A[i];
            i++;
        }
        return sum2 == oneThird;
    }
}

100%

最优解

class Solution {
    public boolean canThreePartsEqualSum(int[] A) {
        int sum = 0;
        for (int i : A) {
            sum += i;
        }
        if (sum % 3 != 0) {
            return false;
        }
        int target = sum / 3;
        int cur_sum = 0;
        int separation = 0;
        for (int i : A) {
            cur_sum += i;
            if (cur_sum == target) {
                separation++;
                cur_sum = 0;
            }
        }
        return (separation == 3) ? true : false;
    }
}

答案的代码比我的好。我一开始担心分出三份后,最后还有一些数比如-6,6。其实没必要,因为只要分出来三份,每份的和都是三分之一,最后即使有剩余的,和也必然为0,不影响结果。

P1018. Binary Prefix Divisible By 5 (Easy)

一个只包含0或1的数组,N_i是指第i个substring从A[0]到A[i].

返回一个boolean的list,如果N_i能被5整除,返回true,否则返回false.

我的思路

一开始想把截止到当前的数累计加起来,然后查看是否能被5整除,结果越界了。因为数组长度为30000, 所以很容易越界。看了一眼答案,每次其实只需要保留余数即可。如果余数乘以2再加下一个数能被5整除,就能被5整除。

我的代码

class Solution {
    public List<Boolean> prefixesDivBy5(int[] A) {
        int curr = 0;
        ArrayList<Boolean> ans = new ArrayList<>();
        for (int i = 0; i < A.length; i++) {
            curr = (int)(((curr * 2 ) + A[i]) % 5);
            ans.add(curr == 0);
        }
        return ans;
    }
}

100%

最优解

class Solution {
    public List<Boolean> prefixesDivBy5(int[] A) {
        if (A == null || A.length == 0) return null;
        List<Boolean> result = new ArrayList<>();
        int[] dp = new int[A.length];
        dp[0] = A[0];
        for (int i = 1; i < A.length; i++) {
            dp[i] = ((dp[i - 1] << 1) + A[i]) % 5;
        }
        for (int i = 0; i < dp.length; i++) {
            result.add(dp[i] == 0);
        }
        return result;
    }
}

P1021. Remove Outermost Parentheses (Easy)

一个有效的括号字符串,移除每个部分最外层的括号

Input: "(()())(())"
Output: "()()()"

我的思路

每遇到一个完整的括号,就取中间的substring,拼接到最终结果中。

我的代码

class Solution {
    public String removeOuterParentheses(String S) {
        char[] chars = S.toCharArray();
        StringBuilder sb = new StringBuilder();
        int start = 1;
        int primitive = 0;
        for (int i = 0; i < chars.length && start < chars.length; i++) {
            if (chars[i] == '(') {
                primitive++;
            } else if (chars[i] == ')') {
                primitive--;
            }
            if (primitive == 0) {
                String s = S.substring(start, i);
                sb.append(s);
                start = i + 2;
            }
        }
        return sb.toString();
    }
}

98%

最优解

class Solution {
    public String removeOuterParentheses(String S) {
        StringBuilder p = new StringBuilder();
        char[] s = S.toCharArray();
        int push_count = 0;
        for(int i=0;i<s.length;i++){
            if(s[i] == '('){
                if(push_count>0)
                    p.append(s[i]);

                ++push_count;
            }
            else{
                --push_count;
                if(push_count>0)
                    p.append(s[i]);
            }

    }
        return p.toString();
    }
}

比我的方法好。每次只需要检查count是否是0即可确定是不是要加到里面。

P1022. Sum of Root To Leaf Binary Numbers (Easy)

一个二叉树,只包含0或1。从根节点到每个叶节点构成的一条路径,就组成了一个二进制的数。返回所有的二进制数的和。

我的思路

前序遍历,每到一个节点都保存到当前为止的路径累加的和。遇到叶节点,就添加到结果中。

我的代码

public class E_1022_SumOfRootToLeafBinaryNumbers  {
    int sum = 0;
    public int sumRootToLeaf(TreeNode root) {
        dfs(root, 0);
        return sum;
    }

    private void dfs(TreeNode node, int sumOfParent) {
        if (node == null) {
           return;
        }
        if (node.left == null && node.right == null) {
            sum += sumOfParent * 2 + node.val;
            return;
        }
        dfs(node.left, sumOfParent * 2 + node.val);
        dfs(node.right, sumOfParent * 2 + node.val);
    }
}

100%

最优解

class Solution {

    public int sumRootToLeaf(TreeNode root){
        return dfs(root, 0);
    }

    private int dfs(TreeNode x, int val){
        if (x == null) return 0;
        val = val * 2 + x.val;
        return (x.left == null && x.right == null)
            ? val
            : dfs(x.left, val) + dfs(x.right, val);
    }
}

P1025. Divisor Game (Easy)

两个人玩一个游戏,黑板上有一个数N。A先选一个x, 使得0 < x < N 同时x能被N整除。最后无法选择的人算输。

我的思路

递归,如果能选出一个数,然后剩下的数导致对方必败,则本方必胜。

答案

class Solution {
    public boolean divisorGame(int N) {
        return N % 2 == 0;
    }
}

偶数必赢,奇数必输。

P1029. Two City Scheduling (Easy)

一个公司计划面试2N个人,第i个人去A城市的成本和B城市的成本,分别用cost[i][0]和cost[i][1]来表示。 A和B各分配N个人。求最小的成本总和。

我的思路

先算出来每个人去A和去B成本的差,用A-B。这个差就是我选择A的影响因子,数值越小,越应该选A。所以把difference排序,选出前N个人。

我的代码

public class E_1029_TwoCityScheduling {
    public int twoCitySchedCost(int[][] costs) {
        int sum = 0;
        int[][] diff = new int[costs.length][2];
        for (int i = 0; i < costs.length; i++) {
            diff[i][0] = costs[i][0] - costs[i][1];
            diff[i][1] = i;
        }
        Arrays.sort(diff, Comparator.comparingInt(o -> o[0]));
        for (int i = 0; i < costs.length; i++) {
            int index = diff[i][1];
            if (i < costs.length / 2) {
                sum += costs[index][0];
            } else {
                sum += costs[index][1];
            }
        }
        return sum;
    }
}

7%

最优解

class Solution {
    public int twoCitySchedCost(int[][] costs) {
        int N2 = costs.length;
    	int[] costs_new = new int[N2];
    	int ans = 0;
        for (int i=0; i<N2; i++) {
        	costs_new[i] = costs[i][1] - costs[i][0];
        	ans += costs[i][0];
        }
        Arrays.sort(costs_new);
        for (int i=0; i<(int)N2/2; i++) {
        	ans += costs_new[i];
        }
        return ans;

    }
}

先把前所有人都选A,然后计算B-A,最后把B-A排序后,加回到总和里,也就是说,A + (B - A)就是对应的需要选B的那些人。

tags: LeetCode