LeetCode 411-430

412. Fizz Buzz

class Solution {
    public List fizzBuzz(int n) {
        List res = new ArrayList<>();
        for (int i = 1; i <= n; i++) {
            if (i % 3 == 0 && i % 5 == 0) {
                res.add("FizzBuzz");
            } else if (i % 3 == 0) {
                res.add("Fizz");
            } else if (i % 5 == 0) {
                res.add("Buzz");
            } else {
                res.add(i + "");
            }
        }
        return res;
    }
}

413. 等差数列划分

class Solution {
    public int numberOfArithmeticSlices(int[] A) {
        int[] dp = new int[A.length];
        int res = 0;
        for (int i = 2; i < A.length; i++) {
            if (A[i] - A[i - 1] == A[i - 1] - A[i - 2]) {
                dp[i] = dp[i - 1] + 1;
                res += dp[i];
            }
        }
        return res;
    }
}

414. 第三大的数

class Solution {
    public int thirdMax(int[] nums) {
        long firstMax = Long.MIN_VALUE;
        long secondMax = Long.MIN_VALUE;
        long thirdMax = Long.MIN_VALUE;
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] == firstMax || nums[i] == secondMax || nums[i] == thirdMax) {
                continue;
            }
            if (nums[i] > firstMax) {
                long temp = firstMax;
                firstMax = nums[i];
                thirdMax = secondMax;
                secondMax = temp;
            } else if (nums[i] > secondMax) {
                thirdMax = secondMax;
                secondMax = nums[i];
            } else if (nums[i] > thirdMax) {
                thirdMax = nums[i];
            }
        }
        return thirdMax == Long.MIN_VALUE ? (int) firstMax : (int) thirdMax;
    }
}

415. 字符串相加

class Solution {
    public String addStrings(String num1, String num2) {
        StringBuilder res = new StringBuilder();
        int carry = 0;
        int k = Math.min(num1.length(), num2.length());
        for (int i = 0; i < k; i++) {
            int a = num1.charAt(num1.length() - i - 1) - '0';
            int b = num2.charAt(num2.length() - i - 1) - '0';
            int sum = a + b + carry;
            carry = sum / 10;
            res.append(sum % 10);
        }
        for (int i = k; i < num1.length(); i++) {
            int a = num1.charAt(num1.length() - i - 1) - '0';
            int sum = a + carry;
            carry = sum / 10;
            res.append(sum % 10);
        }
        for (int i = k; i < num2.length(); i++) {
            int a = num2.charAt(num2.length() - i - 1) - '0';
            int sum = a + carry;
            carry = sum / 10;
            res.append(sum % 10);
        }
        if (carry != 0) {
            res.append(carry);
        }
        res.reverse();
        return res.toString();
    }
}

优化:

class Solution {
    public String addStrings(String num1, String num2) {
        StringBuilder res = new StringBuilder();
        int i = num1.length() - 1;
        int j = num2.length() - 1;
        int carry = 0;
        while (i >= 0 || j >= 0 || carry != 0) {
            int a = i >= 0 ? num1.charAt(i) - '0' : 0;
            int b = j >= 0 ? num2.charAt(j) - '0' : 0;
            int sum = a + b + carry;
            carry = sum / 10;
            res.append(sum % 10);
            i--;
            j--;
        }
        res.reverse();
        return res.toString();
    }
}

416. 分割等和子集

转化成0-1背包,先把数组的所有数之和找出来,如果为奇数,不可能有两个子数组之和相等,直接返回false。
如果为偶数,只要从数组中找到一个子数组的和为sum/2,那么就可以分割等和子集。

dp[i][j]代表数组的前i个数能否找到子集之和为j。
边界:
dp[0][j] = dp[j][0] = false
转移方程:
如果数组的某个数nums[i-1] 刚好等于j,那么dp[i][j]一定为true。
如果nums[i-1]大于j,那么dp[i][j] = dp[i-1][j]
如果nums[i-1]小于j,分两种情况,一种是选第i个数,等于dp[i-1][j-nums[i-1]],一种是不选第i个数,等于dp[i-1][j],只要有一个为真,那么就可以分割。
最后的答案输出dp[i][sum/2]即可。
时间复杂度O(n^2) ,空间复杂度O(n^2)。

class Solution {
    public boolean canPartition(int[] nums) {
        int sum = 0;
        for (int i : nums) {
            sum += i;
        }
        if (sum % 2 == 1) {
            return false;
        }
        int n = nums.length, m = sum / 2;
        boolean[][] dp = new boolean[n + 1][m + 1];

        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                if (nums[i - 1] == j) {
                    dp[i][j] = true;
                } else if (nums[i - 1] > j) {
                    dp[i][j] = dp[i - 1][j];
                } else {
                    dp[i][j] = dp[i - 1][j] || dp[i - 1][j - nums[i-1]];
                }
            }
        }
        return dp[n][m];
    }
}

优化,降维,降空间复杂度降到O(n)

417. 太平洋大西洋水流问题

太耗时了,待优化。

class Solution {
    List> res = new ArrayList<>();
    int[] dirX = {1, -1, 0, 0};
    int[] dirY = {0, 0, 1, -1};
    boolean[][] isVisit;
    boolean flag1 = false;//太平洋
    boolean flag2 = false;//大西洋
    private boolean dfs(int i, int j, int[][] matrix) {
        if (i == 0 && j == matrix[0].length - 1) {
            flag1 = true;
            flag2 = true;
        } else if (i == matrix.length - 1 && j == 0) {
            flag1 = true;
            flag2 = true;
        } else if (i == 0 || j == 0) {
            flag1 = true;
        } else if (i == matrix.length - 1 || j == matrix[0].length - 1) {
            flag2 = true;
        }
        if (flag1 == true && flag2 == true) {
            return true;
        }
        isVisit[i][j] = true;
        for (int flag = 0; flag < 4; flag++) {
            int newI = i + dirX[flag];
            int newJ = j + dirY[flag];
            if (newI >= 0 && newI < matrix.length && newJ >= 0 && newJ < matrix[0].length &&
                    isVisit[newI][newJ] == false && matrix[newI][newJ] <= matrix[i][j] && dfs(newI, newJ, matrix) == true) {
                return true;
            }
        }
        isVisit[i][j] = false;
        return false;
    }
    public List> pacificAtlantic(int[][] matrix) {
        if (matrix.length == 0) {
            return new ArrayList<>();
        }
        if (matrix.length == 1) {
            for (int i = 0; i < matrix[0].length; i++) {
                res.add(Arrays.asList(0, i));
            }
            return res;
        }
        if (matrix[0].length == 1) {
            for (int i = 0; i < matrix.length; i++) {
                res.add(Arrays.asList(i, 0));
            }
            return res;
        }
        isVisit = new boolean[matrix.length][matrix[0].length];
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[0].length; j++) {
                for (int k = 0; k < isVisit.length; k++) {
                    Arrays.fill(isVisit[k], false);
                }
                flag1 = flag2 = false;
                if (dfs(i, j, matrix) == true) {
                    res.add(Arrays.asList(i, j));
                }
            }
        }
        return res;
    }
}

419. 甲板上的战舰

深度优先遍历,找连通块的个数。

class Solution {
    boolean[][] isVisit;
    int[] dirX = {0, 0, 1, -1};
    int[] dirY = {1, -1, 0, 0};
    private void dfs(int i, int j, char[][] board) {
        isVisit[i][j] = true;
        for (int flag = 0; flag < 4; flag++) {
            int newI = i + dirX[flag];
            int newJ = j + dirY[flag];
            if (newI >= 0 && newI < board.length && newJ >= 0 && newJ < board[0].length &&
                    board[newI][newJ] == 'X' && isVisit[newI][newJ] == false) {
                dfs(newI, newJ, board);
            }
        }
    }
    public int countBattleships(char[][] board) {
        int res = 0;
        if (board.length == 0) {
            return 0;
        }
        isVisit = new boolean[board.length][board[0].length];
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[0].length; j++) {
                if (board[i][j] == 'X' && isVisit[i][j] == false) {
                    dfs(i, j, board);
                    res++;
                }
            }
        }
        return res;
    }
}

优化,只统计战舰的头部。
即遇到战舰的头部,计数加1,遇到'.'跳过,遇到战舰的身体部分(左边为'X'或者上面为'X'),跳过。

class Solution {
    public int countBattleships(char[][] board) {
        if (board.length == 0) {
            return 0;
        }
        int res = 0;
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[0].length; j++) {
                if (board[i][j] == '.') {
                    continue;
                }
                if (j-1>=0 &&board[i][j - 1] == 'X') {
                    continue;
                }
                if (i - 1 >= 0 && board[i - 1][j] == 'X') {
                    continue;
                }
                res++;
            }
        }
        return res;
    }
}

421. 数组中两个数的最大异或值

class Solution {
    public int findMaximumXOR(int[] nums) {
        if (nums.length == 1) {
            return 0;
        }
        int res = Integer.MIN_VALUE;
        for (int i = 0; i < nums.length; i++) {
            for (int j = i + 1; j < nums.length; j++) {
                res = Math.max(res, nums[i] ^ nums[j]);
            }
        }
        return res;
    }
}

423. 从英文中重建数字

先统计每个字母出现的次数。
字母z只出现在zero中,字母w只出现在two中,字母u只出现在four中,字母x只出现在six中,字母g只出现在eight中。
字母h只出现在three和eight中,字母f只出现在five和four中,字母s只出现在seven和six中,字母i只出现在nine,five,six,eight中。
字母n只出现在one,nine,seven中。
这样就可以把每个单词出现的次数求出来了。

class Solution {
    public String originalDigits(String s) {
        // building hashmap letter -> its frequency
        char[] count = new char[26 + (int) 'a'];
        for (char letter : s.toCharArray()) {
            count[letter]++;
        }
        // building hashmap digit -> its frequency
        int[] out = new int[10];
        // letter "z" is present only in "zero"
        out[0] = count['z'];
        // letter "w" is present only in "two"
        out[2] = count['w'];
        // letter "u" is present only in "four"
        out[4] = count['u'];
        // letter "x" is present only in "six"
        out[6] = count['x'];
        // letter "g" is present only in "eight"
        out[8] = count['g'];
        // letter "h" is present only in "three" and "eight"
        out[3] = count['h'] - out[8];
        // letter "f" is present only in "five" and "four"
        out[5] = count['f'] - out[4];
        // letter "s" is present only in "seven" and "six"
        out[7] = count['s'] - out[6];
        // letter "i" is present in "nine", "five", "six", and "eight"
        out[9] = count['i'] - out[5] - out[6] - out[8];
        // letter "n" is present in "one", "nine", and "seven"
        out[1] = count['n'] - out[7] - 2 * out[9];
        // building output string
        StringBuilder output = new StringBuilder();
        for (int i = 0; i < 10; i++)
            for (int j = 0; j < out[i]; j++)
                output.append(i);
        return output.toString();
    }
}

424. 替换后的最长重复字符

427. 建立四叉树

429. N 叉树的层序遍历

class Solution {
    public List> levelOrder(Node root) {
        if (root == null) {
            return new ArrayList<>();
        }
        List> res = new ArrayList<>();
        Queue q = new LinkedList<>();
        q.offer(root);
        while (!q.isEmpty()) {
            int size = q.size();
            List list = new ArrayList<>();
            for (int i = 0; i < size; i++) {
                Node front = q.poll();
                list.add(front.val);
                if (front.children.size() != 0) {
                    for (Node n : front.children) {
                        q.offer(n);
                    }
                }
            }
            res.add(list);
        }
        return res;
    }
}

430. 扁平化多级双向链表

class Solution {
    public Node flatten(Node head) {
        if (head == null) {
            return null;
        }
        Node cur = head;
        while (cur != null) {
            if (cur.child != null) {
                Node next = cur.next;
                Node child = flatten(cur.child);
                cur.next = child;
                child.prev = cur;
                cur.child = null;
                if (next != null) {
                    while (cur.next != null) {
                        cur = cur.next;
                    }
                    cur.next = next;
                    next.prev = cur;
                }
            }
            cur = cur.next;
        }
        return head;
    }
}

你可能感兴趣的:(LeetCode 411-430)