文章目录
- 1. 粉刷房子
- 题干:
- 算法原理:
- 1. 状态表示:
- 2. 状态转移方程
- 3. 初始化
- 4. 填表顺序
- 5. 返回值
- 代码:
- 2. 判定字符是否唯一
- 题干:
- 算法原理:
- 1. 哈希表
- 2. 位图思想
- 代码:
- 3. 丢失的数字
- 题干:
- 算法原理:
- 1. 哈希表
- 2. 高斯求和
- 3. 位运算(异或)
- 代码:
- 4. 只出现一次的数字 II
- 题干:
- 算法原理:
- 代码:
- 5. 消失的两个数字
- 题干:
- 算法原理:(位运算)
- 代码:
1. 粉刷房子
原题链接
题干:
每个房子可以被粉刷成红色、蓝色或者绿色这三种颜色
花费是以一个 n x 3 的正整数矩阵 costs
costs[0][0] 表示第 0 号房子粉刷成红色的成本花费
算法原理:
1. 状态表示:
dp[i][0] 表示:粉刷到 i 位置的时候,最后⼀个位置粉刷上「红色」,此时的最小花费
dp[i][1] 表示:粉刷到 i 位置的时候,最后⼀个位置粉刷上「蓝色」,此时的最小花费
dp[i][0] 表示:粉刷到 i 位置的时候,最后⼀个位置粉刷上「绿色」,此时的最小花费
2. 状态转移方程
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. 初始化
- 辅助结点里面的值要「保证后续填表是正确的」
- 「下标的映射关系」
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]));}
}
2. 判定字符是否唯一
原题链接
题干:
确定一个字符串 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;}
}
3. 丢失的数字
原题链接
题干:
包含 [0, n] 中 n 个数的数组 nums
找出 [0, n] 这个范围内没有出现在数组中的那个数
算法原理:
1. 哈希表
两次遍历
2. 高斯求和
3. 位运算(异或)
代码:
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;}
}
4. 只出现一次的数字 II
原题链接
题干:
一个整数数组 nums
除某个元素仅出现 一次 外,其余每个元素都恰出现 三次
找出并返回那个只出现了一次的元素
算法原理:
每一个数的 比特位 可能出现四种情况
我们通过 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;}
}
5. 消失的两个数字
原题链接
题干:
定一个数组,包含从 1 到 N 所有的整数,但其中缺了两个数字
任意顺序返回这两个数字
算法原理:(位运算)
-
将所有的数异或在一起,tmp
tmp = a ^ b -
找到 tmp 中,比特位上为 1 的那一位
-
根据 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;}
}