Jerry's Blog

Recording what I learned everyday

View on GitHub


17 October 2019

LeetCode(40) -- 893, 896, 897, 905, 914

by Jerry Zhang

P893. Groups of Special-Equivalent Strings (Easy)

两个字符串“特殊相等”是指可以互换两个索引同奇或同偶的两个字符任意次。找出一共可以形成多少个这样的特殊相等的组。

我的思路

数一个单词在奇数位上的各个字母和偶数位上的各个字母。

没想对,看答案了。

答案

class Solution {
    public int numSpecialEquivGroups(String[] A) {
        Set<String> seen = new HashSet();
        for (String S: A) {
            int[] count = new int[52];
            for (int i = 0; i < S.length(); ++i)
                count[S.charAt(i) - 'a' + 26 * (i % 2)]++;
            seen.add(Arrays.toString(count));
        }
        return seen.size();
    }
}

其实建一个长为52的数组计数,我也想到了,但是后来想做一个hash value用来比较每个单词的统计情况。答案直接把这个长为52的数组tostring了,然后放到一个HashSet里。

重点是,如果想记录每个字母出现次数这样一个统计数据,可以直接用toString。虽然这样形成的字符串很长,但是可以把它交给Java的hash去想办法。

最优解

class Solution {
    public int numSpecialEquivGroups(String[] A) {
        int grouds = 0;
        Set<Word> set = new HashSet<>();
        for(String s:A) {
            set.add(new Word(s));
        }
        return set.size();
    }

    class Word {
        int[] odd;
        int[] even;
        public Word(String s) {
            odd=new int[26];
            even=new int[26];
            for(int i=0;i<s.length();i++) {
                if(i%2!=0)
                    odd[s.charAt(i)-'a']++;
                else
                    even[s.charAt(i)-'a']++;
            }
        }
        public int hashCode() {
            return Arrays.hashCode(odd) + Arrays.hashCode(even);
        }
        public boolean equals(Object o) {
            Word w = (Word) o;
            for(int i=0;i<w.odd.length;i++) {
                if(w.odd[i]!=this.odd[i]) return false;
                if(w.even[i]!=this.even[i]) return false;
            }
            return true;
            }
    }
}

这个非常值得学习!新做了一个Word类,同时重写equals和hashcode方法,这样再用HashSet时就能自动调动这两个方法,实现hash

Arrays.hashCode()方法可以非常方便的给一个算出一个array的hashcode。那这个新实现的类,因为有两个数组,就把它们简单相加,或者用IDE默认的重写hash方法,一个hash乘以31再加上另一个hash。

P896. Monotonic Array (Easy)

判断一个数组是否是单调的(递增或递减)可重复。

我的思路

直接遍历判断就好了。跟上一题相比简单到极点了。

我的代码

class Solution {
    public boolean isMonotonic(int[] A) {
        boolean increasing = true;
        boolean decreasing = true;
        for (int i = 1; i < A.length; i++) {
            if (A[i] > A[i - 1]) {
                decreasing = false;
            }
            if (A[i] < A[i - 1]) {
                increasing = false;
            }
        }
        return increasing || decreasing;
    }
}

75%

最优解

class Solution {
    public boolean isMonotonic(int[] A) {
        if(A.length==1 || A.length==0)
            return true;
        //is increasing
        boolean isIncreasing=true;
        for(int i=0;i<A.length-1;i++){
            if(A[i+1]<A[i]){
                isIncreasing=false;
                break;
            }
        }
        boolean isDeacreasing= true;
        for(int i=0;i<A.length-1;i++){
            if(A[i+1]>A[i]){
                isDeacreasing=false;
                break;
            }
        }
        return isIncreasing || isDeacreasing;
    }
}

跟我代码几乎完全一样。

P897. Increasing Order Search Tree (Easy)

中序遍历一棵树,然后把它的最左边的节点作为根节点,变成一个只有右节点的线性树。

我的思路

中序遍历然后存成一个新树即可。

我的代码

public class E_897_IncreasingOrderSearchTree {
    TreeNode ans;
    TreeNode current;
    public TreeNode increasingBST(TreeNode root) {
        inOrder(root);
        return ans;
    }

    private void inOrder(TreeNode node) {
        if (node == null) {
            return;
        }
        inOrder(node.left);
        if (ans == null) {
            ans = new TreeNode(node.val);
            current = ans;
        } else {
            current.right = new TreeNode(node.val);
            current = current.right;
        }
        inOrder(node.right);
    }
}

100%

最优解

class Solution {

     TreeNode cur;
    public TreeNode increasingBST(TreeNode root) {
        TreeNode ans = new TreeNode(0);
        cur = ans;
        inorder(root);
        return ans.right;
    }

    public void inorder(TreeNode node) {
        if (node == null) return;
        inorder(node.left);
        node.left = null;
        cur.right = node;
        cur = node;
        inorder(node.right);
    }
}

不需要新建节点,用原来的节点即可。

P905. Sort Array By Parity (Easy)

一个非负整数数组,返回一个数组使它所有偶数都是前面,所有奇数都放后面。顺序无所谓。

我的思路

先挑一遍偶数,再挑一遍奇数。

我的代码

class Solution {
    public int[] sortArrayByParity(int[] A) {
        int[] ans = new int[A.length];
        int j = 0;
        for (int i = 0; i < A.length; i++) {
            if (A[i] % 2 == 0) {
                ans[j] = A[i];
                j++;
            }
        }
        for (int i = 0; i < A.length; i++) {
            if (A[i] % 2 != 0) {
                ans[j] = A[i];
                j++;
            }
        }
        return ans;
    }
}

100%

最优解

class Solution {
    private void swap(int[] a, int x, int y) {
        int tmp = a[x];
        a[x] = a[y];
        a[y] = tmp;
    }

    public int[] sortArrayByParity(int[] A) {
        int N = A.length;
        int[] ans = Arrays.copyOf(A, N);
        int i=0;
        int j=N-1;
        while (i < j) {
            while(ans[i]%2==0&&i<j) i+=1;
            while(ans[j]%2!=0&&i<j) j-=1;
            if((i<j)&&(ans[i]%2!=0)&&(ans[j]%2==0)) {
                swap(ans, i, j);
                i += 1;
                j -= 1;
            }
//            System.out.printf("i=%d,j=%d\n",i,j);
        }
//        System.out.println(Arrays.toString(ans));
//        System.out.println();
        return ans;
    }
}

P914. X of a Kind in a Deck of Cards (Easy)

有一组卡牌,每张牌上都有一个整数。问是否能分组,使每组都有X张牌且数字相等?(X >= 2)

我的思路

上周竞赛题weekly158也有一道分组的题,也是不知道每组里有几个数,但是每组的数字要相同。

我的代码

class Solution {
    public boolean hasGroupsSizeX(int[] deck) {
        int[] count = new int[10000];
        for (int i = 0; i < deck.length; i++) {
            count[deck[i]]++;
        }
        int min = Integer.MAX_VALUE;
        for (int i : count) {
            if (i > 0) {
                min = Math.min(min, i);
            }
        }
        if (min < 2) {
            return false;
        }
        for (int i : count) {
            if (i > min && findGCD(i, min) < 2) {
                return false;
            }
        }
        return true;
    }

    private int findGCD(int number1, int number2) {
        if(number2 == 0){
            return number1;
        }
        return findGCD(number2, number1 % number2);
    }
}

98%

最优解

class Solution {
    public boolean hasGroupsSizeX(int[] arr) {
        int[] res = new int[10001];
        for(int i: arr){
            res[i]++;
        }
        int min = 0;
        for(int j=0;j<10001;j++){
            if(res[j]!=0){
                if(res[j]<2) return false;
                if(min==0) {
                    min = res[j];
                }else{
                    min = gcd(min,res[j]);
                    if(min<2)return false;
                }
            }
        }
		return true;
    }

    private int gcd(int x, int y) {
		return x == 0 ? y : gcd(y % x, x);
	}
}

答案:

class Solution {
    public boolean hasGroupsSizeX(int[] deck) {
        int[] count = new int[10000];
        for (int c: deck)
            count[c]++;

        int g = -1;
        for (int i = 0; i < 10000; ++i)
            if (count[i] > 0) {
                if (g == -1)
                    g = count[i];
                else
                    g = gcd(g, count[i]);
            }

        return g >= 2;
    }

    public int gcd(int x, int y) {
        return x == 0 ? y : gcd(y%x, x);
    }
}
tags: LeetCode