LeetCode习题集 有些题可能直接略过了,整理一下之前刷leetcode

461. 汉明距离

两个整数之间的汉明距离指的是这两个数字对应二进制位不同的位置的数目。

给出两个整数 x 和 y,计算它们之间的汉明距离。

注意: 0 ≤ x, y < 231.

示例:

输入: x = 1, y = 4

输出: 2

解释: 1 (0 0 0 1) 4 (0 1 0 0) ↑ ↑

上面的箭头指出了对应二进制位不同的位置。

    找两个数字,二进制下,相同位置不同数字的数目
    异或下,如果二进制相同位的数字不一样就返回一
    我们把异或的结果,看一共有多少个1
        每次都检测最后一位是不是1
        如果是1,就加上,然后把当前位删除
        
        一直循环到异或的结果为0
class Solution {
    public int hammingDistance(int x, int y) {
    int z = x ^ y;
	int sum = 0;
	while (z!=0){
		sum += z & 1;
		z = z>>1;
	}
	return sum;
    }
}

462. 最少移动次数使数组元素相等 II

给定一个非空整数数组,找到使所有数组元素相等所需的最小移动数,其中每次移动可将选定的一个元素加1或减1。 您可以假设数组的长度最多为10000。

例如:

输入: [1,2,3]

输出: 2

说明: 只有两个动作是必要的(记得每一步仅可使其中一个元素加1或减1):

[1,2,3] => [2,2,3] => [2,2,2]

给数组排个序
    双指针,一个从0,一个从末尾
    右指针的值-左指针的值
        这么做的意义是,他俩的平均值是相加除2   
        左指针的值要加到平均值,右指针的值要减到平均值
        相当于就是    平均值-左指针+右指针-平均值
                化简就是    右指针-左指针
class Solution {
       public int minMoves2(int[] nums) {
    	int res=0,i=0,j=nums.length-1;
    	Arrays.sort(nums);
    	while (i < j) {
            res += nums[j--] - nums[i++];
        }
        return res;
    }
}

463. 岛屿的周长

给定一个包含 0 和 1 的二维网格地图,其中 1 表示陆地 0 表示水域。

网格中的格子水平和垂直方向相连(对角线方向不相连)。整个网格被水完全包围,但其中恰好有一个岛屿(或者说,一个或多个表示陆地的格子相连组成的岛屿)。

岛屿中没有“湖”(“湖” 指水域在岛屿内部且不和岛屿周围的水相连)。格子是边长为 1 的正方形。网格为长方形,且宽度和高度均不超过 100 。计算这个岛屿的周长。

示例 :

输入: [[0,1,0,0], [1,1,1,0], [0,1,0,0], [1,1,0,0]]

输出: 16

解释: 它的周长是下面图片中的 16 个黄色的边:

在这里插入图片描述

class Solution {
    public int islandPerimeter(int[][] grid) {
        int num = 0;
        for(int i = 0; i < grid.length; i++) {
            for(int j = 0; j < grid[i].length; j++) {
                if(grid[i][j] == 1) {
                    num = num + 4;   
                    //如果grid[i+1][j]不超出数组并且也等于1(岛)则边减2
                    if(i + 1 < grid.length && grid[i + 1][j] == 1) {
                        num = num -2;
                    }
                    //如果grid[i][j+1]不超出数组并且也等于1(岛)则边减2
                    if(j + 1 < grid[i].length  && grid[i][j + 1] == 1) {
                        num = num -2;
                    }
                }
            }
        }
        return num;
    }
}

466. 统计重复个数

定义由 n 个连接的字符串 s 组成字符串 S,即 S = [s,n]。例如,["abc", 3]=“abcabcabc”。

另一方面,如果我们可以从 s2 中删除某些字符使其变为 s1,我们称字符串 s1 可以从字符串 s2 获得。例如,“abc” 可以根据我们的定义从 “abdbec” 获得,但不能从 “acbbe” 获得。

现在给出两个非空字符串 S1 和 S2(每个最多 100 个字符长)和两个整数 0 ≤ N1 ≤ 106 和 1 ≤ N2 ≤ 106。现在考虑字符串 S1 和 S2,其中S1=[s1,n1]和S2=[s2,n2]。找出可以使[S2,M]从 S1 获得的最大整数 M。

示例:

输入: s1 ="acb",n1 = 4 s2 ="ab",n2 = 2

返回: 2

class Solution {
    public int getMaxRepetitions(String s1, int n1, String s2, int n2) {
        if(s1 == null || s2 == null) return 0;
        int n = s1.length(), m = s2.length();
        int index = 0, cnt = 0;
        int[] count = new int[m+2], nxt = new int[m+2];
        for(int i = 1; i <= m + 1 && i <= n1; ++i){
            for(int j = 0; j < n; ++j){
                if(s2.charAt(index) == s1.charAt(j)) index++;
                if(index >= m){
                    index = 0;
                    cnt++;
                }
            }
            count[i] = cnt;
            nxt[i] = index;
            for(int j = 1; j < i; ++j){
                if(nxt[j] == nxt[i]){
                    int repeat = count[i] - count[j];
                    int repeat_num = repeat * ((n1 - j) / (i - j));
                    int remain_num = count[j + (n1 - j) % (i - j)];
                    return (repeat_num + remain_num) / n2;
                }
            }
        }
        return count[n1] / n2;
    }
}

467. 环绕字符串中唯一的子字符串

把字符串 s 看作是“abcdefghijklmnopqrstuvwxyz”的无限环绕字符串,所以 s 看起来是这样的:"...zabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd....".

现在我们有了另一个字符串 p 。你需要的是找出 s 中有多少个唯一的 p 的非空子串,尤其是当你的输入是字符串 p ,你需要输出字符串 s 中 p 的不同的非空子串的数目。

注意: p 仅由小写的英文字母组成,p 的大小可能超过 10000。

示例 1:

输入: "a" 输出: 1 解释: 字符串 S 中只有一个"a"子字符。

示例 2:

输入: "cac" 输出: 2 解释: 字符串 S 中的字符串“cac”只有两个子串“a”、“c”。.

示例 3:

输入: "zab" 输出: 6 解释: 在字符串 S 中有六个子串“z”、“a”、“b”、“za”、“ab”、“zab”。.

PS: 唯一的子字符串的数量就等于:分别以a,b, c, d。。。z结尾的最长子字符串的长度之后;注意, 不能统计重复的, 那么, 以z为例, 以z结尾的最长子字符串的长度, 就是, 以z结尾的“唯一”的子字符串的数量;

class Solution {
    public int findSubstringInWraproundString(String p) {
       
        int n = p.length();
        if(n < 1) return 0;
        int ret = 0;
        int[] count = new int[26];
        char[] str = p.toCharArray();
        int curMaxLen = 1;
        for(int i = 0; i < n; ++i) {
            if(i > 0 && (str[i]-str[i-1] == 1 || str[i-1]-str[i] == 25))
                curMaxLen++;
            else
                curMaxLen = 1;
            count[str[i]-'a'] = Math.max(count[str[i]-'a'], curMaxLen);
        }
        for(int temp : count)
            ret += temp;
        return ret;
    }
}

468. 验证IP地址

编写一个函数来验证输入的字符串是否是有效的 IPv4 或 IPv6 地址。

IPv4 地址由十进制数和点来表示,每个地址包含4个十进制数,其范围为 0 - 255, 用(".")分割。比如,172.16.254.1;

同时,IPv4 地址内的数不会以 0 开头。比如,地址 172.16.254.01 是不合法的。

IPv6 地址由8组16进制的数字来表示,每组表示 16 比特。这些组数字通过 (":")分割。比如, 2001:0db8:85a3:0000:0000:8a2e:0370:7334 是一个有效的地址。而且,我们可以加入一些以 0 开头的数字,字母可以使用大写,也可以是小写。所以, 2001:db8:85a3:0:0:8A2E:0370:7334 也是一个有效的 IPv6 address地址 (即,忽略 0 开头,忽略大小写)。

然而,我们不能因为某个组的值为 0,而使用一个空的组,以至于出现 (::) 的情况。 比如, 2001:0db8:85a3::8A2E:0370:7334 是无效的 IPv6 地址。

同时,在 IPv6 地址中,多余的 0 也是不被允许的。比如, 02001:0db8:85a3:0000:0000:8a2e:0370:7334 是无效的。

说明: 你可以认为给定的字符串里没有空格或者其他特殊字符。

示例 1:

输入: "172.16.254.1"

输出: "IPv4"

解释: 这是一个有效的 IPv4 地址, 所以返回 "IPv4"。 示例 2:

输入: "2001:0db8:85a3:0:0:8A2E:0370:7334"

输出: "IPv6"

解释: 这是一个有效的 IPv6 地址, 所以返回 "IPv6"。 示例 3:

输入: "256.256.256.256"

输出: "Neither"

解释: 这个地址既不是 IPv4 也不是 IPv6 地址。

	听大佬们说,Java有验证IP的方法,但我不会用,希望大佬能指点一些
class Solution {
    public String validIPAddress(String IP) {
    //防止开头和结尾是“:”和“.”,会扰乱后面split的判断:52 / 79 "2001:0db8:85a3:0:0:8A2E:0370:7334:"
        if(IP.startsWith(":")||IP.startsWith(".")
           ||IP.endsWith(":")||IP.endsWith(".")) return "Neither";
        String[] splitted = IP.split("\\.");
        if(splitted.length==4){
            int num=-1;
            for(int i=0;i<4;i++){
                try{
                    num=Integer.parseInt(splitted[i]);
                }catch(NumberFormatException e){
                    return "Neither";
                }
                if(num<0||num>255) return "Neither";
                //防止IPv4中的0开头的情况:65 / 79 "01.01.01.01";还有防止-0的情况:76 / 79 "15.16.-0.1"
                if(splitted[i].length()>1
                   &&(splitted[i].startsWith("0")||splitted[i].startsWith("-")))
                    return "Neither";
            }
            return "IPv4";
        }else{
            splitted = IP.split(":");
            if(splitted.length==8){
                int num=-1;
                for(int i=0;i<8;i++){
                    int len = splitted[i].length();
                    if(splitted[i]==null
                       ||len>4
                       ||len==0) return "Neither";
                    for(int j=0;j<len;j++){
                        char c = splitted[i].charAt(j);
                        if(!((c>='0'&&c<='9')||(c>='a'&&c<='f')||(c>='A'&&c<='F'))) return "Neither";
                    }
                }
                return "IPv6";
            }else return "Neither";
        }
    }
}

470. 用 Rand7() 实现 Rand10()

已有方法 rand7 可生成 1 到 7 范围内的均匀随机整数,试写一个方法 rand10 生成 1 到 10 范围内的均匀随机整数。

不要使用系统的 Math.random() 方法。

示例 1:

输入: 1 输出: [7] 示例 2:

输入: 2 输出: [8,4] 示例 3:

输入: 3 输出: [8,1,10]

提示:

rand7 已定义。 传入参数: n 表示 rand10 的调用次数。

进阶:

rand7()调用次数的 期望值 是多少 ? 你能否尽量少调用 rand7() ?

当作二维矩阵来看
因为是七的随机数
    那么我们组合起来就是:十位*7+当前位,只要大于四十说明都可以出现的    1-9
    那么我们就返回就可以了,只要最后一位, %10以后不会存在10的,我们把目标值-1在%10 算完在+1 还是原来的值
/**
 * The rand7() API is already defined in the parent class SolBase.
 * public int rand7();
 * @return a random integer in the range 1 to 7
 */
class Solution extends SolBase {
    public int rand10() { 
        int row, col, idx;
        do {
            row = rand7();
            col = rand7();
            idx = col + (row - 1) * 7;
        } while (idx > 40);
        return 1 + (idx - 1) % 10;
    }
    }