每个房子可以被粉刷成红色、蓝色或者绿色这三种颜色
花费是以一个 n x 3 的正整数矩阵 costs
costs[0][0] 表示第 0 号房子粉刷成红色的成本花费
dp[i][0] 表示:粉刷到 i 位置的时候,最后⼀个位置粉刷上「红色」,此时的最小花费
dp[i][1] 表示:粉刷到 i 位置的时候,最后⼀个位置粉刷上「蓝色」,此时的最小花费
dp[i][0] 表示:粉刷到 i 位置的时候,最后⼀个位置粉刷上「绿色」,此时的最小花费
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]
从左往右,三个表⼀起填
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]));
}
}
确定一个字符串 s 的所有字符是否全都不同
时间复杂度为 O(n)
空间复杂度为 O(n)
直接创建一个大小为 26 的 hash 表就可以了
每⼀个「比特位」代表⼀个「字符」,⼀个 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;
}
}
包含 [0, n] 中 n 个数的数组 nums
找出 [0, n] 这个范围内没有出现在数组中的那个数
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;
}
}
一个整数数组 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;
}
}
定一个数组,包含从 1 到 N 所有的整数,但其中缺了两个数字
任意顺序返回这两个数字
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;
}
}