leetcode443-475中的简单题

443. 字符串压缩

题目:
给定一组字符,使用原地算法将其压缩。

压缩后的长度必须始终小于或等于原数组长度。

数组的每个元素应该是长度为1 的字符(不是 int 整数类型)。

在完成原地修改输入数组后,返回数组的新长度。

思路:
设置两个标志,一个标识字母第一次出现的位置,另一个计算此字母出现的次数;用返回值作为char[]的索引并进行字母和数字的插入。

代码:

class Solution {
    public int compress(char[] chars) {
        int len = chars.length;
        if(len<=1) return len;
        int count = 0,i = 0,j = 1, cur = -1;
        while(j<=len){
            if(j!=len&&chars[i]==chars[j]){
                count++;
                j++;
            }
            if(j==len||chars[i]!=chars[j]){
                chars[++cur] = chars[i];
                if(cur+1<=len-1&&count!=0){
                    for(char c:((count+1)+"").toCharArray())
                        chars[++cur]=c;
                }
                i=j;
                j++;
                count=0;
            }
        }
        return cur+1;
    }
}

447. 回旋镖的数量

题目:
给定平面上 n 对不同的点,“回旋镖” 是由点表示的元组 (i, j, k) ,其中 i 和 j 之间的距离和 i 和 k 之间的距离相等(需要考虑元组的顺序)。

找到所有回旋镖的数量。你可以假设 n 最大为 500,所有点的坐标在闭区间 [-10000, 10000] 中。

例子:
输入:
[[0,0],[1,0],[2,0]]
输出:
2
解释:
两个回旋镖为 [[1,0],[0,0],[2,0]] 和 [[1,0],[2,0],[0,0]]

思想:
没做出来,抄的。。

JAVA 实现: 这道题思路其实也比较简单,计算一点和其他点之间的距离,使用哈希表存储,若同一距离出现多次,则可以形成回旋镖。假设同一距离出现 n 次,由数字规律可推出回旋镖的数量 sum = n*(n-1) 。本人开始只能做到存储到哈希表,然后按该公式累加得到最后结果。参考了速度第一的答案,优化如下:假设当前同一距离的数量为 n, 回旋镖数量为 n*(n-1), 当再出现一个同一距离时,回旋镖的数量应为 (n+1)n,与之前相差 (n+1)n - n(n-1) = 2n, 所以只需要把最后答案加上 2*n, 最后 n+1 再存储到哈希表中。

代码:

class Solution {
    public int numberOfBoomerangs(int[][] points) {
        int len = points.length;
        int ans = 0;
        Map<Double,Integer> map = new HashMap<>();
        for(int i = 0;i < len;i++){
            for(int j = 0;j < len;j++){
                if(i!=j){
                    double dis = Math.pow(points[i][0] - points[j][0],2)
                                +Math.pow(points[i][1] - points[j][1],2);
                    if(!map.containsKey(dis)){
                        map.put(dis,1);
                    }else{
                        int n = map.get(dis);
                        ans += 2*n;
                        map.put(dis,n + 1);
                    }
                }
            }
            map.clear();
        }
        return ans;
    }
}

448. 找到所有数组中消失的数字

题目:
给定一个范围在 1 ≤ a[i] ≤ n ( n = 数组大小 ) 的 整型数组,数组中的元素一些出现了两次,另一些只出现一次。

找到所有在 [1, n] 范围之间没有出现在数组中的数字。

您能在不使用额外空间且时间复杂度为O(n)的情况下完成这个任务吗? 你可以假定返回的数组不算在额外空间内。

示例:
输入:
[4,3,2,7,8,2,3,1]
输出:
[5,6]

思路:
使用数组的下标来标记数字的出现于否,通过一遍遍历即可标记出全部已经出现的数组。

代码:

class Solution {
    public List<Integer> findDisappearedNumbers(int[] nums) {
        List<Integer> list  = new ArrayList<>();
        int len = nums.length;
        for(int i =0;i<len;i++){
            if(nums[Math.abs(nums[i]) - 1] > 0){
                nums[Math.abs(nums[i]) - 1] = -nums[Math.abs(nums[i]) - 1];
            }
        }
        for(int i=0;i<len;i++){
            if(nums[i]>0) list.add(i+1);
        }
        return list;
    }
}

453. 最小移动次数使数组元素相等

题目:
给定一个长度为n的数组,找出最少的移动次数使得数组中的所有元素都相等,一次操作为将数组中n-1各元素加1

思路:
移动次数等于所有元素和最小值相减的和。

代码:

class Solution {
    public int minMoves(int[] nums) {
        int len = nums.length;
        int minNum = nums[0];
        int result = 0;
        for(int i=0;i<len;i++){
            if(nums[i]<minNum) minNum = nums[i];
        }
        for(int i=0;i<len;i++){
            if(nums[i]>minNum){
                result += nums[i] - minNum;
            }
        }
        return result;
    }
}

455. 分发饼干

题目:
假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。对每个孩子 i ,都有一个胃口值 gi ,这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j ,都有一个尺寸 sj 。如果 sj >= gi ,我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。

思路:
对两个数组进行排序,通过一遍遍历得到结果。

代码:

class Solution {
    public int minMoves(int[] nums) {
        int len = nums.length;
        int minNum = nums[0];
        int result = 0;
        for(int i=0;i<len;i++){
            if(nums[i]<minNum) minNum = nums[i];
        }
        for(int i=0;i<len;i++){
            if(nums[i]>minNum){
                result += nums[i] - minNum;
            }
        }
        return result;
    }
}

459. 重复的子字符串

题目:
给定一个非空的字符串,判断它是否可以由它的一个子串重复多次构成。给定的字符串只含有小写英文字母,并且长度不超过10000。

思路:
自己看代码吧,我写出来的太烂了,看看别人第一怎么写的。。。

代码:

class Solution {
    public boolean repeatedSubstringPattern(String s) {
        int[] primes = new int[]{2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97};
        int l = s.length();
        for (int i : primes) {
            if (i > l) break;
            if (l % i == 0) {
                boolean valid = true;
                int j = l / i;
                for (int n = l; n > j; n -= j) {
                    if (!s.substring(n - j, n).equals(s.substring(n - 2 * j, n - j))) {
                        valid = false;
                        break;
                    }
                }
                if (valid) return true;
            }
        }
        return false;
    }
}//耗时0ms,速度无敌

461. 汉明距离

题目:
计算两个整数之间的汉明顿距离(长度在31位以内)

分析:
异或运算得出所有不同为1的位,每次进行向右或者向左移位相加就能得到。也可以参考一下java里是怎么实现汉明顿距离的。

代码:

class Solution {
    public int hammingDistance(int x, int y) {

	    int z = x ^ y;
	    int sum = 0;
	    while (z!=0){
            System.out.println(z&1);
		    sum += z & 1;
		    z = z>>1;
	    }
	    return sum;

    }
}

463. 岛屿的周长

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

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

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

在这里插入图片描述
思路:
递归求解;
或者双重for循环每次遇到值为1的方块就加一;同时判断当前方块右边相邻的是不是也是1,如果是就去掉他俩相邻的鞭(-2);同时判断当前方块下边相邻的是不是也是1,如果是就去掉他俩相邻的鞭(-2)。

代码:

class Solution {
    public int islandPerimeter(int[][] grid) {
        for(int i=0;i<grid.length;i++){
            for(int j=0;j<grid[0].length;j++){
                if(grid[i][j]==1)
                    return dfs(grid,i,j);
            }
        }
        return 0;
    }
    
    int  dfs(int[][] grid, int r, int c){
        if(!(0<=r && r<grid.length && 0<=c && c<grid[0].length)) return 1;
        
        if(grid[r][c]==0) return 1;
        
        if(grid[r][c]!=1) return 0;
        
        grid[r][c]=2;
        
        return dfs(grid,r-1,c)+dfs(grid,r+1,c)+dfs(grid,r,c-1)+dfs(grid,r,c+1);
    }
}

class Solution {
    public int islandPerimeter(int[][] grid) {
        if (grid == null || grid.length == 0) return 0;
        int rows = grid.length;
        int cols = grid[0].length;
        int ones = 0;
        int connects = 0;
        for (int row = 0; row < rows; row++) {
            for (int col = 0; col < cols; col++) {
                if (grid[row][col] == 1) {
                    ones++;
                    if (col + 1 < cols && grid[row][col+1] == 1) connects++;
                    if (row + 1 < rows && grid[row+1][col] == 1) connects++;
                }
            }
        }
        return 4 * ones - 2 * connects;
    }
}

475. 供暖器

题目:
冬季已经来临。 你的任务是设计一个有固定加热半径的供暖器向所有房屋供暖。

现在,给出位于一条水平线上的房屋和供暖器的位置,找到可以覆盖所有房屋的最小加热半径。

所以,你的输入将会是房屋和供暖器的位置。你将输出供暖器的最小加热半径。

说明:

给出的房屋和供暖器的数目是非负数且不会超过 25000。
给出的房屋和供暖器的位置均是非负数且不会超过10^9。
只要房屋位于供暖器的半径内(包括在边缘上),它就可以得到供暖。
所有供暖器都遵循你的半径标准,加热的半径也一样。
示例 1:

输入: [1,2,3],[2]
输出: 1
解释: 仅在位置2上有一个供暖器。如果我们将加热半径设为1,那么所有房屋就都能得到供暖。

思路:
对于每个房屋,要么用前面的暖气,要么用后面的,二者取近的,得到距离;
对于所有的房屋,选择最大的上述距离。

代码:

class Solution {
    public int findRadius(int[] houses, int[] heaters) {
        Arrays.sort(houses);
        Arrays.sort(heaters);
        int heaterLen = heaters.length;
        int pos = 0;
        int res = 0;
        for(int house : houses){
            while(pos+1<heaterLen&&heaters[pos]<house){
                pos++;
            }
            if(pos==0){
                res = Math.max(res,Math.abs(heaters[pos] - house));
            }else{
                res = Math.max(res,Math.min(Math.abs(heaters[pos-1]-house),Math.abs(heaters[pos]-house)));
            }
        }
        return res;
    }
}

476. 数字的补数

题目:
给定一个正整数,输出它的补数。补数是对该数的二进制表示取反。

思路:
获取一个和输入相同长度的最大数字,再进行异或运算就可。

代码:

class Solution {
    public int findComplement(int num) {
        int temp = num,c = 0;
        while(temp>0){
            temp >>= 1;
            c = (c<<1) + 1;
        }
        return num^c;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值