【LeetCode】Day 4

版权声明:--(●'◡'●)-- --(●ˇ∀ˇ●)-- https://blog.csdn.net/qq_36032149/article/details/85221372

500. Keyboard Row

Given a List of words, return the words that can be typed using letters of alphabet on only one row’s of American keyboard like the image below.
在这里插入图片描述
Example:

Input: [“Hello”, “Alaska”, “Dad”, “Peace”]
Output: [“Alaska”, “Dad”]

题意:
如果一个单词中每个字母都属于键盘的同一行,则输出。

	
   

    public String[] findWords(String[] words) {
        List<String> list = new ArrayList<>(words.length);
        for (String word : words) {
            if (is2(word)) {
                list.add(word);
            }
        }
        return list.toArray(new String[0]);
    }
	//方法1
	String[] ss = {
            "qwertyuiop",
            "asdfghjkl",
            "zxcvbnm"
    };
    //O(m * n)
    boolean is(String word) {
        for (String s : ss) {
            if (s.indexOf((char) (word.charAt(0) | 32)) != -1) {// OR 32(0x20) toLowerCase
                for (int i = 1; i < word.length(); i++) {
                    if (s.indexOf((char) (word.charAt(i) | 32)) == -1) {
                        return false;
                    }
                }
                return true;
            }
        }
        return false;
    }
     //方法2
    //0代表属于第一排,1第二排,2第三排字母
    int[] ii = {1, 2, 2, 1, 0, 1, 1, 1, 0, 1, 1, 1, 2, 2, 0, 0, 0, 0, 1, 0, 0, 2, 0, 2, 0, 2};
    //O(n)
    boolean is2(String word) {
        //得到第一个属于哪一行,后面的必须和他同一行,才能返回true
        char c0 = word.charAt(0);
        int r = ii[(c0 | 32) - 'a'];// OR 32(0x20) toLowerCase
        for (int i = 1; i < word.length(); i++) {
            if (ii[(word.charAt(i) | 32) - 'a'] != r) {
                return false;
            }
        }
        return true;
    }

872. Leaf-Similar Trees

Consider all the leaves of a binary tree. From left to right order, the values of those leaves form a leaf value sequence.

在这里插入图片描述
For example, in the given tree above, the leaf value sequence is (6, 7, 4, 9, 8).

Two binary trees are considered leaf-similar if their leaf value sequence is the same.

Return true if and only if the two given trees with head nodes root1 and root2 are leaf-similar.

题意:
判断两颗二叉树叶子节点序列是否相同(如图叶子节点为[6,7,4,9,8])

    public boolean leafSimilar(TreeNode root1, TreeNode root2) {
        List<Integer> l1 = new ArrayList<>();
        List<Integer> l2 = new ArrayList<>();
        getLeaf(root1, l1);
        getLeaf(root2, l2);
        if(l1.size() != l2.size()) return false;
        for(int i = 0; i < l1.size(); i++){
            if(l1.get(i) != l2.get(i))return false;
        }
        return true;
    }
    //递归获取树节点,添加到List中
    void getLeaf(TreeNode node, List<Integer> list) {
        if (node != null) {
            if(node.left == null && node.right == null) {
                list.add(node.val);//如果左右节点都为null,说明当前节点为叶子节点,添加到List中
            }else{//否则,递归寻找叶子节点
                getLeaf(node.left, list);
                getLeaf(node.right, list);
            }
        }
    }

893. Groups of Special-Equivalent Strings

You are given an array A of strings.

Two strings S and T are special-equivalent if after any number of moves, S == T.

A move consists of choosing two indices i and j with i % 2 == j % 2, and swapping S[i] with S[j].

Now, a group of special-equivalent strings from A is a non-empty subset S of A such that any string not in S is not special-equivalent with any string in S.

Return the number of groups of special-equivalent strings from A.
Example 1:

Input: [“a”,“b”,“c”,“a”,“c”,“c”]
Output: 3
Explanation: 3 groups [“a”,“a”], [“b”], [“c”,“c”,“c”]
Example 2:

Input: [“aa”,“bb”,“ab”,“ba”]
Output: 4
Explanation: 4 groups [“aa”], [“bb”], [“ab”], [“ba”]
Example 3:

Input: [“abc”,“acb”,“bac”,“bca”,“cab”,“cba”]
Output: 3
Explanation: 3 groups [“abc”,“cba”], [“acb”,“bca”], [“bac”,“cab”]
Example 4:

Input: [“abcd”,“cdab”,“adcb”,“cbad”]
Output: 1
Explanation: 1 group [“abcd”,“cdab”,“adcb”,“cbad”]

题意:
没读懂题目,待续…

766. Toeplitz Matrix

Toeplitz Matrix 是一种 左上 到 右下 连线的元素相等 的矩阵
Example:

Input:
matrix = [
[1,2,3,4],
[5,1,2,3],
[9,5,1,2]
]
Output: True
Explanation:
In the above grid, the diagonals are:
“[9]”, “[5, 5]”, “[1, 1, 1]”, “[2, 2, 2]”, “[3, 3]”, “[4]”.
In each diagonal all elements are the same, so the answer is True.

matrix[i][j] 和 matrix[i + 1][j + 1] 进行比较,如果有一个不相等,返回false

    public boolean isToeplitzMatrix(int[][] matrix) {
        int rowLen = matrix.length;
        int colLen = matrix[0].length;
        for (int i = 0; i < rowLen - 1; i++) {
            for (int j = 0; j < colLen - 1; j++) {
                if(matrix[i][j] != matrix[i + 1][j + 1]) {
                    return false;
                }
            }
        }   
        return true;
    }

884. Uncommon Words from Two Sentences

找出两个句子中不重复且不同的单词
We are given two sentences A and B. (A sentence is a string of space separated words. Each word consists only of lowercase letters.)
A word is uncommon if it appears exactly once in one of the sentences, and does not appear in the other sentence.
Return a list of all uncommon words.
You may return the list in any order.

Example:

Input: A = “this apple is sweet”, B = “this apple is sour”
Output: [“sweet”,“sour”]

Input: A = “apple apple”, B = “banana”
Output: [“banana”]
直接用Map吧元素都装进去,遍历出个数为一的元素

    public String[] uncommonFromSentences(String A, String B) {
        String[] AA = A.split(" ");
        String[] BB = B.split(" ");
        Map<String,Integer> map = new HashMap<>();
        for(String a: AA) {
            map.put(a, map.getOrDefault(a, 0) + 1);
        }
        for(String b: BB) {
            map.put(b, map.getOrDefault(b, 0) + 1);
        }
        List<String> list = new ArrayList<>();

        for(Map.Entry<String, Integer> entry: map.entrySet()){
            if (entry.getValue() == 1) list.add(entry.getKey());
        }
        return list.toArray(new String[0]);
    }

897. Increasing Order Search Tree

Given a tree, rearrange the tree in in-order so that the leftmost node in the tree is now the root of the tree, and every node has no left child and only 1 right child.

Example 1:
Input: [5,3,6,2,4,null,8,1,null,null,null,7,9]

       5
      / \
    3    6
   / \    \
  2   4    8
 /        / \ 
1        7   9

Output: [1,null,2,null,3,null,4,null,5,null,6,null,7,null,8,null,9]

 1
  \
   2
    \
     3
      \
       4
        \
         5
          \
           6
            \
             7
              \
               8
                \
                 9  

中序遍历 每个节点的值 添加到树节点的右子节点


    private TreeNode result = new TreeNode(-1);
    private TreeNode head = result;

    public TreeNode increasingBST(TreeNode root) {
        helper(root);
        return head.right;
    }

    private void helper(TreeNode root) {
        if (root != null) {
            helper(root.left);
            
            result.right = new TreeNode(root.val);
            result = result.right;
            
            helper(root.right);
        }
    }

463. Island Perimeter

you are given a map in form of a two-dimensional integer grid where 1 represents land and 0 represents water.

Grid cells are connected horizontally/vertically (not diagonally). The grid is completely surrounded by water, and there is exactly one island (i.e., one or more connected land cells).

The island doesn’t have “lakes” (water inside that isn’t connected to the water around the island). One cell is a square with side length 1. The grid is rectangular, width and height don’t exceed 100. Determine the perimeter of the island.

Input:
[[0,1,0,0],
[1,1,1,0],
[0,1,0,0],
[1,1,0,0]]
Output: 16
Explanation: The perimeter is the 16 yellow stripes in the image below:
在这里插入图片描述

求周长

	//暴力解,每个格子边长为4,上下左右每有一个相邻就-1
    public int islandPerimeter(int[][] grid) {
        int s = 0;
        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[i].length; j++) {
                if (grid[i][j] == 1) {
                    s += 4;
                    if (j < grid[i].length - 1 && grid[i][j + 1] == 1) {
                        s--;
                    }
                    if (i < grid.length - 1 && grid[i + 1][j] == 1) {
                        s--;
                    }
                    if (j > 0 && grid[i][j - 1] == 1) {
                        s--;
                    }
                    if (i > 0 && grid[i - 1][j] == 1) {
                       s--;
                    }
                }
            }
        }
        return s;
    }
    //仔细观察周长,格子数,邻居数的关系,发现 周长 = 4倍格子数 - 2倍相邻数
    public int islandPerimeter(int[][] grid) {
        if(grid == null || grid.length == 0 || grid[0].length == 0) return 0;
        int s = 0, n = 0;
        int row = grid.length;
        int col = grid[0].length;
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                if (grid[i][j] == 1) {
                    s++;//数出格子的数量
                    if(j < col - 1 && grid[i][j + 1] == 1) {
                        n++;//相邻+1
                    }
                    if(i < row - 1 && grid[i+1][j] == 1) {
                        n++;//相邻+1
                    }
                }
            }
        }
        return 4 * s - 2 * n;
    }
    //把上面的化简一下,每次直接遇到格子+4,遇到相邻的-2
    public int islandPerimeter(int[][] grid) {
        if(grid == null || grid.length == 0 || grid[0].length == 0) return 0;
        int s = 0;
        int row = grid.length;
        int col = grid[0].length;
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                if (grid[i][j] == 1) {
                    s += 4;
                    if(j < col - 1 && grid[i][j + 1] == 1) {
                        s -= 2;
                    }
                    if(i < row - 1 && grid[i+1][j] == 1) {
                        s -= 2;
                    }
                }
            }
        }
        return s;
    }

682. Baseball Game

You’re now a baseball game point recorder.

Given a list of strings, each string can be one of the 4 following types:

Integer (one round’s score): Directly represents the number of points you get in this round.
“+” (one round’s score): Represents that the points you get in this round are the sum of the last two valid round’s points.
“D” (one round’s score): Represents that the points you get in this round are the doubled data of the last valid round’s points.
“C” (an operation, which isn’t a round’s score): Represents the last valid round’s points you get were invalid and should be removed.
Each round’s operation is permanent and could have an impact on the round before and the round after.

You need to return the sum of the points you could get in all the rounds.

Input: [“5”,“2”,“C”,“D”,"+"]
Output: 30
Explanation:
Round 1: You could get 5 points. The sum is: 5.
Round 2: You could get 2 points. The sum is: 7.
Operation 1: The round 2’s data was invalid. The sum is: 5.
Round 3: You could get 10 points (the round 2’s data has been removed). The sum is: 15.
Round 4: You could get 5 + 10 = 15 points. The sum is: 30.

Input: [“5”,"-2",“4”,“C”,“D”,“9”,"+","+"]
Output: 27
Explanation:
Round 1: You could get 5 points. The sum is: 5.
Round 2: You could get -2 points. The sum is: 3.
Round 3: You could get 4 points. The sum is: 7.
Operation 1: The round 3’s data is invalid. The sum is: 3.
Round 4: You could get -4 points (the round 3’s data has been removed). The sum is: -1.
Round 5: You could get 9 points. The sum is: 8.
Round 6: You could get -4 + 9 = 5 points. The sum is 13.
Round 7: You could get 9 + 5 = 14 points. The sum is 27.

    public int calPoints(String[] ops) {
        int sum = 0, v = 0, len = ops.length;
        int[] valid = new int[len];//保存有效数字
        for(int i = 0, k = 0; i < len; i++){
            switch (ops[i]) {
            	//如果是"+", sum加上前两个有效数字之和,然后把有效数字之和作为最新的一个有效数字
                case "+": v = valid[k - 2] + valid[k - 1];sum += v; valid[k++] = v; break;
                //如果是"C", sum减去上一个有效数字,并移除
                case "C": sum -= valid[--k]; break;
                //如果是"D", sum加上上一个有效数字的两倍,然后把这个两倍数作为最新的有效数字
                case "D": v = valid[k - 1] * 2; sum += v; valid[k++] = v; break;
                //如果是数字, 直接加到sum里和有效数字中
                default : v = Integer.parseInt(ops[i]); sum += v; valid[k++] = v;
            }
        }
        return sum;
    }

669. Trim a Binary Search Tree

二叉树剪枝
Given a binary search tree and the lowest and highest boundaries as L and R, trim the tree so that all its elements lies in [L, R] (R >= L). You might need to change the root of the tree, so the result should return the new root of the trimmed binary search tree.

Example1:

Input: 
    1
   / \
  0   2

  L = 1
  R = 2

Output: 
    1
      \
       2

Example2:

Input: 
    3
   / \
  0   4
   \
    2
   /
  1

  L = 1
  R = 3

Output: 
      3
     / 
   2   
  /
 1
    public TreeNode trimBST(TreeNode root, int L, int R) {
        if (root != null) {
        	//如果当前节点小于左边界,即[root,...,L,...,R,...],只需要剪右边的子树,扔掉左边
            if (root.val < L) return trimBST(root.right, L, R);    
            //如果当前节点大于右边界,即[...,L,...,R,...,root],只需要剪左边的子树,扔掉右边
            if(root.val > R) return trimBST(root.left, L, R);  
            //新树的左子树为原左子树裁剪后得到的新树
            root.left = trimBST(root.left, L, R);
            //新树的右子树为原右子树裁剪后得到的新树
            root.right = trimBST(root.right, L, R);
        }
        return root;
    }

868. Binary Gap

Given a positive integer N, find and return the longest distance between two consecutive 1’s in the binary representation of N.

If there aren’t two consecutive 1’s, return 0.

Input: 22
Output: 2
Explanation:
22 in binary is 0b10110.
In the binary representation of 22, there are three ones, and two consecutive pairs of 1’s.
The first consecutive pair of 1’s have distance 2.
The second consecutive pair of 1’s have distance 1.
The answer is the largest of these two distances, which is 2.

Input: 5
Output: 2
Explanation:
5 in binary is 0b101.

Input: 6
Output: 1
Explanation:
6 in binary is 0b110.

Input: 8
Output: 0
Explanation:
8 in binary is 0b1000.
There aren’t any consecutive pairs of 1’s in the binary representation of 8, so we return 0.

一个数的二进制形式,求 连续的两个1的最大距离

5(0b0101) 最大距离为2
9(0b1001) 最大距离为3
13(0b1101)最大距离为2

	//解法1,N右移遍历每一个1,用i记录当前1的位置,j记录上一个1的位置
    public int binaryGap(int N) {
        int max = 0;
        while ((N & 1) == 0) N >>= 1;//先把低位的0全跳过
        for (int cur = 0, last = 0; N > 0; N >>= 1, cur++) {
            if ((N & 1) == 1) {//如果当前位为1
                if (cur - last > max) {//如果cur-last比之前的最大值还大,更新最大距离
                    max = cur - last;
                }
                last = cur;//当前位置保存到last
            }
        }
        return max;
    }
	//解法2,用一个idx=1左移,然后和N做与(&)运算,判断N当前位是否为1
    public int binaryGap2(int N) {
        int max = 0;
        for (int cur = 0, idx = 1, last = -1; idx < N; idx <<= 1, cur++) {//last初始化为-1,表示还未赋过值
            if ((N & idx) == idx) {//如果当前位为1
                if (last != -1 && cur - last > max) {
                    max = cur - last;
                }
                last = cur;
            }
        }
        return max;
    }

575. Distribute Candies

兄妹分糖果,没人各一半,求妹妹最多能分到几种糖果
Given an integer array with even length, where different numbers in this array represent different kinds of candies. Each number means one candy of the corresponding kind. You need to distribute these candies equally in number to brother and sister. Return the maximum number of kinds of candies the sister could gain.

Example:

Input: candies = [1,1,2,2,3,3]
Output: 3
Explanation:
There are three different kinds of candies (1, 2 and 3), and two candies for each kind.
Optimal distribution: The sister has candies [1,2,3] and the brother has candies [1,2,3], too.
The sister has three different kinds of candies.

Input: candies = [1,1,2,3]
Output: 2
Explanation: For example, the sister has candies [2,3] and the brother has candies [1,1].
The sister has two different kinds of candies, the brother has only one kind of candies.

计算出不重复的糖果种类数,
假如不重复糖果总数小于总数的一半,那这一半全给妹妹,就是结果
如果大于总数的一半,那妹妹的最大不同种类糖果数就为总数的一半

	//解法1,Set求不重复的种类数
    public int distributeCandies(int[] candies) {
        int n = candies.length / 2;
        Set<Integer> set = new HashSet<>(candies.length);
        for (int candy : candies) {
        	if (!set.cntains(candy)) {
        		set.add(candy);
        	}
        }
        return set.size() > n ? n : set.size();
    }
    //解法2,由于糖果数以及种类都是题目限定好的,用一个bool数组代替Set。
    public int distributeCandies(int[] candies) {
        int n = candies.length / 2, count = 0;
        boolean[] set = new boolean[200_001];
        for (int candy : candies) {
            if (!set[candy + 100_000]) {
                if(++count >= n) return n;
                set[candy + 100_000] = true;
            }
        }
        return count;
    }

猜你喜欢

转载自blog.csdn.net/qq_36032149/article/details/85221372