【算法刷题】Day25

文章目录

  • 1. 粉刷房子
    • 题干:
    • 算法原理:
      • 1. 状态表示:
      • 2. 状态转移方程
      • 3. 初始化
      • 4. 填表顺序
      • 5. 返回值
    • 代码:
  • 2. 判定字符是否唯一
    • 题干:
    • 算法原理:
      • 1. 哈希表
      • 2. 位图思想
    • 代码:
  • 3. 丢失的数字
    • 题干:
    • 算法原理:
      • 1. 哈希表
      • 2. 高斯求和
      • 3. 位运算(异或)
    • 代码:
  • 4. 只出现一次的数字 II
    • 题干:
    • 算法原理:
    • 代码:
  • 5. 消失的两个数字
    • 题干:
    • 算法原理:(位运算)
    • 代码:

1. 粉刷房子

【算法刷题】Day25_第1张图片
原题链接


题干:

每个房子可以被粉刷成红色、蓝色或者绿色这三种颜色
花费是以一个 n x 3 的正整数矩阵 costs
costs[0][0] 表示第 0 号房子粉刷成红色的成本花费
【算法刷题】Day25_第2张图片


算法原理:

1. 状态表示:

dp[i][0] 表示:粉刷到 i 位置的时候,最后⼀个位置粉刷上「红色」,此时的最小花费

dp[i][1] 表示:粉刷到 i 位置的时候,最后⼀个位置粉刷上「蓝色」,此时的最小花费

dp[i][0] 表示:粉刷到 i 位置的时候,最后⼀个位置粉刷上「绿色」,此时的最小花费

2. 状态转移方程

【算法刷题】Day25_第3张图片
dp[i][0] = min(dp[i - 1][1], dp[i- 1][2]) + costs[i - 1][0]
dp[i][1] = min(dp[i - 1][0], dp[i - 1][2]) + costs[i - 1][1]
dp[i][2] = min(dp[i - 1][0], dp[i - 1][1]) + costs[i - 1][2]

3. 初始化

【算法刷题】Day25_第4张图片

  1. 辅助结点里面的值要「保证后续填表是正确的」
  2. 「下标的映射关系」

4. 填表顺序

从左往右,三个表⼀起填

5. 返回值

min(dp[n][0], min(dp[n][1], dp[n][2]))


代码:

class Solution {
    public int minCost(int[][] costs) {
        int n = costs.length;
        int[][] dp = new int[n + 1][3];
        for(int i = 1; i <= n; i++) {
            dp[i][0] = Math.min(dp[i - 1][1], dp[i - 1][2]) + costs[i - 1][0];
            dp[i][1] = Math.min(dp[i - 1][0], dp[i - 1][2]) + costs[i - 1][1];
            dp[i][2] = Math.min(dp[i - 1][0], dp[i - 1][1]) + costs[i - 1][2];
        }
        return Math.min(dp[n][0], Math.min(dp[n][1], dp[n][2]));
    }
}

【算法刷题】Day25_第5张图片


2. 判定字符是否唯一

【算法刷题】Day25_第6张图片
原题链接


题干:

确定一个字符串 s 的所有字符是否全都不同


算法原理:

1. 哈希表

时间复杂度为 O(n)
空间复杂度为 O(n)
直接创建一个大小为 26 的 hash 表就可以了

2. 位图思想

每⼀个「比特位」代表⼀个「字符」,⼀个 int 类型的变量的 32 位足够表示所有的小写字⺟
比特位里面如果是 0 ,表示这个字符没有出现过
比特位里面的值是 1 ,表示该字符出现过

优化点:
运用“鸽巢原理”
len > 26 说明一定有重复的字符


代码:

class Solution {
    public boolean isUnique(String astr) {
        if(astr.length() > 26) {
            return false;
        }
        int map = 0;
        for(int i = 0; i < astr.length(); i++) {
            int x = astr.charAt(i) - 'a';
            if(((map >> x) & 1) == 1) {
                return false;
            }
            map |= (1 << x);
        }
        return true;
    }
}

【算法刷题】Day25_第7张图片


3. 丢失的数字

【算法刷题】Day25_第8张图片
原题链接


题干:

包含 [0, n] 中 n 个数的数组 nums
找出 [0, n] 这个范围内没有出现在数组中的那个数


算法原理:

1. 哈希表

两次遍历
【算法刷题】Day25_第9张图片

2. 高斯求和

【算法刷题】Day25_第10张图片

3. 位运算(异或)

【算法刷题】Day25_第11张图片


代码:

class Solution {
    public int missingNumber(int[] nums) {
        int ret = 0;
        for(int i = 0; i < nums.length; i++) {
            ret ^= nums[i];
        }
        for(int i = 0; i <= nums.length; i++) {
            ret ^= i;
        }
        return ret;
    }
}

【算法刷题】Day25_第12张图片


4. 只出现一次的数字 II

【算法刷题】Day25_第13张图片
原题链接


题干:

一个整数数组 nums
除某个元素仅出现 一次 外,其余每个元素都恰出现 三次
找出并返回那个只出现了一次的元素


算法原理:

【算法刷题】Day25_第14张图片
每一个数的 比特位 可能出现四种情况
我们通过 ret 的每⼀个比特位上的值,就可以将 ret 给还原出来


代码:

class Solution {
    public int singleNumber(int[] nums) {
        int ret = 0;
        for(int i = 0; i < 32; i++) {
            int sum = 0;
            for(int x : nums) {//统计 sum 中所有的数的第 i 位的和
                if(((x >> i) & 1) == 1) {
                    sum++;
                }
            }
            sum %= 3;
            if(sum == 1) {
                ret |= 1 << i;
            }
        }
        return ret;
    }
}

【算法刷题】Day25_第15张图片


5. 消失的两个数字

【算法刷题】Day25_第16张图片
原题链接


题干:

定一个数组,包含从 1 到 N 所有的整数,但其中缺了两个数字
任意顺序返回这两个数字


算法原理:(位运算)

【算法刷题】Day25_第17张图片

  1. 将所有的数异或在一起,tmp
    tmp = a ^ b

  2. 找到 tmp 中,比特位上为 1 的那一位
    【算法刷题】Day25_第18张图片

  3. 根据 x 为的不同,划分为两类异或


代码:

class Solution {
    public int[] missingTwo(int[] nums) {
        //1. 先把所有的数异或在一起
        int tmp = 0;
        for(int x : nums) {
            tmp ^= x;
        }
        for(int i = 1; i <= nums.length + 2; i++) {
            tmp ^= i;
        }

        //2. 找出 a, b 两个数比特位不同的哪一位
        int diff = 0;
        while(true) {
            if(((tmp >> diff) & 1) == 1) {
                break;
            }else {
                diff++;
            }
        }

        //3. 将所有的数按照 diff 位不同,分两类异或
        int[] ret = new int[2];
         for(int x : nums) {
            if(((x >> diff) & 1) == 1) {
                ret[1] ^= x;
            }else {
                ret[0] ^= x;
            }
        }
        for(int i = 1; i <= nums.length + 2; i++) {
            if(((i >> diff) & 1) == 1) {
                ret[1] ^= i;
            }else {
                ret[0] ^= i;
            }
        }
        return ret;
    }
}

【算法刷题】Day25_第19张图片


你可能感兴趣的:(算法刷题,算法,java)