添加 problem 318、371、389、393、397、405、421、461、476、477、693、756、762、898

This commit is contained in:
YDZ
2019-07-12 03:09:08 +08:00
parent e2f8465d9f
commit 90c42f817a
42 changed files with 1686 additions and 0 deletions

View File

@ -0,0 +1,23 @@
package leetcode
func maxProduct318(words []string) int {
if words == nil || len(words) == 0 {
return 0
}
length, value, maxProduct := len(words), make([]int, len(words)), 0
for i := 0; i < length; i++ {
tmp := words[i]
value[i] = 0
for j := 0; j < len(tmp); j++ {
value[i] |= 1 << (tmp[j] - 'a')
}
}
for i := 0; i < length; i++ {
for j := i + 1; j < length; j++ {
if (value[i]&value[j]) == 0 && (len(words[i])*len(words[j]) > maxProduct) {
maxProduct = len(words[i]) * len(words[j])
}
}
}
return maxProduct
}

View File

@ -0,0 +1,52 @@
package leetcode
import (
"fmt"
"testing"
)
type question318 struct {
para318
ans318
}
// para 是参数
// one 代表第一个参数
type para318 struct {
one []string
}
// ans 是答案
// one 代表第一个答案
type ans318 struct {
one int
}
func Test_Problem318(t *testing.T) {
qs := []question318{
question318{
para318{[]string{"abcw", "baz", "foo", "bar", "xtfn", "abcdef"}},
ans318{16},
},
question318{
para318{[]string{"a", "ab", "abc", "d", "cd", "bcd", "abcd"}},
ans318{4},
},
question318{
para318{[]string{"a", "aa", "aaa", "aaaa"}},
ans318{0},
},
}
fmt.Printf("------------------------Leetcode Problem 318------------------------\n")
for _, q := range qs {
_, p := q.ans318, q.para318
fmt.Printf("【input】:%v 【output】:%v\n", p, maxProduct318(p.one))
}
fmt.Printf("\n\n\n")
}

View File

@ -0,0 +1,46 @@
# [318. Maximum Product of Word Lengths](https://leetcode.com/problems/maximum-product-of-word-lengths/)
## 题目:
Given a string array `words`, find the maximum value of `length(word[i]) * length(word[j])` where the two words do not share common letters. You may assume that each word will contain only lower case letters. If no such two words exist, return 0.
**Example 1:**
Input: ["abcw","baz","foo","bar","xtfn","abcdef"]
Output: 16
Explanation: The two words can be "abcw", "xtfn".
**Example 2:**
Input: ["a","ab","abc","d","cd","bcd","abcd"]
Output: 4
Explanation: The two words can be "ab", "cd".
**Example 3:**
Input: ["a","aa","aaa","aaaa"]
Output: 0
Explanation: No such pair of words.
## 题目大意
给定一个字符串数组 words找到 length(word[i]) * length(word[j]) 的最大值,并且这两个单词不含有公共字母。你可以认为每个单词只包含小写字母。如果不存在这样的两个单词,返回 0。
## 解题思路
- 在字符串数组中找到 2 个没有公共字符的字符串,并且这两个字符串的长度乘积要是最大的,求这个最大的乘积。
- 这里需要利用位运算 `&` 运算的性质,如果 `X & Y = 0`,说明 X 和 Y 完全不相同。那么我们将字符串都编码成二进制数,进行 `&` 运算即可分出没有公共字符的字符串,最后动态维护长度乘积最大值即可。将字符串编码成二进制数的规则比较简单,每个字符相对于 'a' 的距离,根据这个距离将 1 左移多少位。
```c
a 1->1
b 2->10
c 4->100
ab 3->11
ac 5->101
abc 7->111
az 33554433->10000000000000000000000001
```

View File

@ -0,0 +1,13 @@
package leetcode
func getSum(a int, b int) int {
if a == 0 {
return b
}
if b == 0 {
return a
}
// (a & b)<<1 计算的是进位
// a ^ b 计算的是不带进位的加法
return getSum((a&b)<<1, a^b)
}

View File

@ -0,0 +1,49 @@
package leetcode
import (
"fmt"
"testing"
)
type question371 struct {
para371
ans371
}
// para 是参数
// one 代表第一个参数
type para371 struct {
a int
b int
}
// ans 是答案
// one 代表第一个答案
type ans371 struct {
one int
}
func Test_Problem371(t *testing.T) {
qs := []question371{
question371{
para371{1, 2},
ans371{3},
},
question371{
para371{-2, 3},
ans371{1},
},
// 如需多个测试,可以复制上方元素。
}
fmt.Printf("------------------------Leetcode Problem 371------------------------\n")
for _, q := range qs {
_, p := q.ans371, q.para371
fmt.Printf("【input】:%v 【output】:%v\n", p, getSum(p.a, p.b))
}
fmt.Printf("\n\n\n")
}

View File

@ -0,0 +1,26 @@
# [371. Sum of Two Integers](https://leetcode.com/problems/sum-of-two-integers/)
## 题目:
Calculate the sum of two integers a and b, but you are **not allowed** to use the operator `+` and `-`.
**Example 1:**
Input: a = 1, b = 2
Output: 3
**Example 2:**
Input: a = -2, b = 3
Output: 1
## 题目大意
不使用运算符 + 和 - ​​​​​​​,计算两整数 a 、b ​​​​​​​之和。
## 解题思路
- 要求不用加法和减法运算符计算 `a+b`。这一题需要用到 `^``&` 运算符的性质,两个数 ^ 可以实现两个数不带进位的二进制加法。这里需要实现加法,肯定需要进位。所以如何找到进位是本题的关键。
- 在二进制中,只有 1 和 1 加在一起才会进位0 和 00 和 11 和 0这三种情况都不会进位规律就是 `a & b` 为 0 的时候就不用进位,为 1 的时候代表需要进位。进位是往前进一位,所以还需要左移操作,所以加上的进位为 `(a&b)<<1`

View File

@ -0,0 +1,10 @@
package leetcode
func findTheDifference(s string, t string) byte {
n, ch := len(t), t[len(t)-1]
for i := 0; i < n-1; i++ {
ch ^= s[i]
ch ^= t[i]
}
return ch
}

View File

@ -0,0 +1,45 @@
package leetcode
import (
"fmt"
"testing"
)
type question389 struct {
para389
ans389
}
// para 是参数
// one 代表第一个参数
type para389 struct {
s string
t string
}
// ans 是答案
// one 代表第一个答案
type ans389 struct {
one byte
}
func Test_Problem389(t *testing.T) {
qs := []question389{
question389{
para389{"abcd", "abcde"},
ans389{'e'},
},
// 如需多个测试,可以复制上方元素。
}
fmt.Printf("------------------------Leetcode Problem 389------------------------\n")
for _, q := range qs {
_, p := q.ans389, q.para389
fmt.Printf("【input】:%v 【output】:%v\n", p, findTheDifference(p.s, p.t))
}
fmt.Printf("\n\n\n")
}

View File

@ -0,0 +1,30 @@
# [389. Find the Difference](https://leetcode.com/problems/find-the-difference/)
## 题目:
Given two strings **s** and **t** which consist of only lowercase letters.
String **t** is generated by random shuffling string **s** and then add one more letter at a random position.
Find the letter that was added in **t**.
**Example:**
Input:
s = "abcd"
t = "abcde"
Output:
e
Explanation:
'e' is the letter that was added.
## 题目大意
给定两个字符串 s 和 t它们只包含小写字母。字符串 t 由字符串 s 随机重排,然后在随机位置添加一个字母。请找出在 t 中被添加的字母。
## 解题思路
- 题目要求找出 t 字符串中比 s 字符串多出的一个字符。思路还是利用异或的性质,`X^X = 0`,将 s 和 t 依次异或,最终多出来的字符就是最后异或的结果。

View File

@ -0,0 +1,26 @@
package leetcode
func validUtf8(data []int) bool {
count := 0
for _, d := range data {
if count == 0 {
if d >= 248 { // 11111000 = 248
return false
} else if d >= 240 { // 11110000 = 240
count = 3
} else if d >= 224 { // 11100000 = 224
count = 2
} else if d >= 192 { // 11000000 = 192
count = 1
} else if d > 127 { // 01111111 = 127
return false
}
} else {
if d <= 127 || d >= 192 {
return false
}
count--
}
}
return count == 0
}

View File

@ -0,0 +1,47 @@
package leetcode
import (
"fmt"
"testing"
)
type question393 struct {
para393
ans393
}
// para 是参数
// one 代表第一个参数
type para393 struct {
one []int
}
// ans 是答案
// one 代表第一个答案
type ans393 struct {
one bool
}
func Test_Problem393(t *testing.T) {
qs := []question393{
question393{
para393{[]int{197, 130, 1}},
ans393{true},
},
question393{
para393{[]int{235, 140, 4}},
ans393{false},
},
}
fmt.Printf("------------------------Leetcode Problem 393------------------------\n")
for _, q := range qs {
_, p := q.ans393, q.para393
fmt.Printf("【input】:%v 【output】:%v\n", p, validUtf8(p.one))
}
fmt.Printf("\n\n\n")
}

View File

@ -0,0 +1,71 @@
# [393. UTF-8 Validation](https://leetcode.com/problems/utf-8-validation/)
## 题目:
A character in UTF8 can be from **1 to 4 bytes** long, subjected to the following rules:
1. For 1-byte character, the first bit is a 0, followed by its unicode code.
2. For n-bytes character, the first n-bits are all one's, the n+1 bit is 0, followed by n-1 bytes with most significant 2 bits being 10.
This is how the UTF-8 encoding would work:
Char. number range | UTF-8 octet sequence
(hexadecimal) | (binary)
--------------------+---------------------------------------------
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
Given an array of integers representing the data, return whether it is a valid utf-8 encoding.
**Note:**The input is an array of integers. Only the **least significant 8 bits** of each integer is used to store the data. This means each integer represents only 1 byte of data.
**Example 1:**
data = [197, 130, 1], which represents the octet sequence: 11000101 10000010 00000001.
Return true.
It is a valid utf-8 encoding for a 2-bytes character followed by a 1-byte character.
**Example 2:**
data = [235, 140, 4], which represented the octet sequence: 11101011 10001100 00000100.
Return false.
The first 3 bits are all one's and the 4th bit is 0 means it is a 3-bytes character.
The next byte is a continuation byte which starts with 10 and that's correct.
But the second continuation byte does not start with 10, so it is invalid.
## 题目大意
UTF-8 中的一个字符可能的长度为 1 到 4 字节,遵循以下的规则:
对于 1 字节的字符,字节的第一位设为 0后面 7 位为这个符号的 unicode 码。
对于 n 字节的字符 (n > 1),第一个字节的前 n 位都设为 1第 n+1 位设为 0后面字节的前两位一律设为 10。剩下的没有提及的二进制位全部为这个符号的 unicode 码。
这是 UTF-8 编码的工作方式:
```c
Char. number range | UTF-8 octet sequence
(hexadecimal) | (binary)
--------------------+---------------------------------------------
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
```
给定一个表示数据的整数数组,返回它是否为有效的 utf-8 编码。
注意:
输入是整数数组。只有每个整数的最低 8 个有效位用来存储数据。这意味着每个整数只表示 1 字节的数据。
## 解题思路
- 这一题看似很复杂,其实严格按照 UTF8 定义来模拟就可以了。

View File

@ -0,0 +1,16 @@
package leetcode
func integerReplacement(n int) int {
res := 0
for n > 1 {
if (n & 1) == 0 { // 判断是否是偶数
n >>= 1
} else if (n+1)%4 == 0 && n != 3 { // 末尾 2 位为 11
n++
} else { // 末尾 2 位为 01
n--
}
res++
}
return res
}

View File

@ -0,0 +1,47 @@
package leetcode
import (
"fmt"
"testing"
)
type question397 struct {
para397
ans397
}
// para 是参数
// one 代表第一个参数
type para397 struct {
s int
}
// ans 是答案
// one 代表第一个答案
type ans397 struct {
one int
}
func Test_Problem397(t *testing.T) {
qs := []question397{
question397{
para397{8},
ans397{3},
},
question397{
para397{7},
ans397{4},
},
}
fmt.Printf("------------------------Leetcode Problem 397------------------------\n")
for _, q := range qs {
_, p := q.ans397, q.para397
fmt.Printf("【input】:%v 【output】:%v\n", p, integerReplacement(p.s))
}
fmt.Printf("\n\n\n")
}

View File

@ -0,0 +1,62 @@
# [397. Integer Replacement](https://leetcode.com/problems/integer-replacement/)
## 题目:
Given a positive integer n and you can do operations as follow:
1. If  n is even, replace  n with `n/2`.
2. If  n is odd, you can replace n with either `n + 1` or `n - 1`.
What is the minimum number of replacements needed for n to become 1?
**Example 1:**
Input:
8
Output:
3
Explanation:
8 -> 4 -> 2 -> 1
**Example 2:**
Input:
7
Output:
4
Explanation:
7 -> 8 -> 4 -> 2 -> 1
or
7 -> 6 -> 3 -> 2 -> 1
## 题目大意
给定一个正整数 n你可以做如下操作
1. 如果 n 是偶数则用 n / 2 替换 n。
2. 如果 n 是奇数则可以用 n + 1 或 n - 1 替换 n。
问 n 变为 1 所需的最小替换次数是多少?
## 解题思路
- 题目给出一个整数 `n`,然后让我们通过变换将它为 1如果 `n` 是偶数,可以直接变为 `n/2`,如果是奇数,可以先 `n+1``n-1`,问最终变为 1 的最少步骤。
- 当 n 为奇数的时候,什么时候需要加 1 ,什么时候需要减 1 ,通过观察规律可以发现,除了 3 和 7 以外,所有加 1 就变成 4 的倍数的奇数,都适合先加 1 运算,比如 15:
15 -> 16 -> 8 -> 4 -> 2 -> 1
15 -> 14 -> 7 -> 6 -> 3 -> 2 -> 1
111011 -> 111010 -> 11101 -> 11100 -> 1110 -> 111 -> 1000 -> 100 -> 10 -> 1
111011 -> 111100 -> 11110 -> 1111 -> 10000 -> 1000 -> 100 -> 10 -> 1
- 对于 7 来说,加 1 和减 1 的结果相同,可以不用管,对于 3 来说,减 1 的步骤更少,所以需要先去掉这种特殊情况。
- 最后如何判断某个数字加 1 后是 4 的倍数呢?这里有一个小技巧,由于之前判断了其是奇数了,那么最右边一位肯定是 1如果其右边第二位也是 1 的话,那么进行加 1 运算,进位后右边肯定会出现两个 0则一定是 4 的倍数。于是就可以判断出来了。剩下的情况就是偶数的情况,如果之前判定是偶数,那么直接除以 2 (右移一位)即可。

View File

@ -0,0 +1,24 @@
package leetcode
func toHex(num int) string {
if num == 0 {
return "0"
}
if num < 0 {
num += 1 << 32
}
mp := map[int]string{
0: "0", 1: "1", 2: "2", 3: "3", 4: "4", 5: "5", 6: "6", 7: "7", 8: "8", 9: "9",
10: "a", 11: "b", 12: "c", 13: "d", 14: "e", 15: "f",
}
var bitArr []string
for num > 0 {
bitArr = append(bitArr, mp[num%16])
num /= 16
}
str := ""
for i := len(bitArr) - 1; i >= 0; i-- {
str += bitArr[i]
}
return str
}

View File

@ -0,0 +1,47 @@
package leetcode
import (
"fmt"
"testing"
)
type question405 struct {
para405
ans405
}
// para 是参数
// one 代表第一个参数
type para405 struct {
one int
}
// ans 是答案
// one 代表第一个答案
type ans405 struct {
one string
}
func Test_Problem405(t *testing.T) {
qs := []question405{
question405{
para405{26},
ans405{"1a"},
},
question405{
para405{-1},
ans405{"ffffffff"},
},
}
fmt.Printf("------------------------Leetcode Problem 405------------------------\n")
for _, q := range qs {
_, p := q.ans405, q.para405
fmt.Printf("【input】:%v 【output】:%v\n", p, toHex(p.one))
}
fmt.Printf("\n\n\n")
}

View File

@ -0,0 +1,48 @@
# [405. Convert a Number to Hexadecimal](https://leetcode.com/problems/convert-a-number-to-hexadecimal/)
## 题目:
Given an integer, write an algorithm to convert it to hexadecimal. For negative integer, [twos complement](https://en.wikipedia.org/wiki/Two%27s_complement) method is used.
**Note:**
1. All letters in hexadecimal (`a-f`) must be in lowercase.
2. The hexadecimal string must not contain extra leading `0`s. If the number is zero, it is represented by a single zero character `'0'`; otherwise, the first character in the hexadecimal string will not be the zero character.
3. The given number is guaranteed to fit within the range of a 32-bit signed integer.
4. You **must not use any method provided by the library** which converts/formats the number to hex directly.
**Example 1:**
Input:
26
Output:
"1a"
**Example 2:**
Input:
-1
Output:
"ffffffff"
## 题目大意
给定一个整数,编写一个算法将这个数转换为十六进制数。对于负整数,我们通常使用[补码运算](https://baike.baidu.com/item/%E8%A1%A5%E7%A0%81/6854613?fr=aladdin)方法。
注意:
1. 十六进制中所有字母(a-f)都必须是小写。
2. 十六进制字符串中不能包含多余的前导零。如果要转化的数为 0那么以单个字符 '0' 来表示;对于其他情况,十六进制字符串中的第一个字符将不会是 0 字符。 
3. 给定的数确保在 32 位有符号整数范围内。
4. 不能使用任何由库提供的将数字直接转换或格式化为十六进制的方法。
## 解题思路
- 这一题是水题,将十进制数转换成十六进制的数。需要额外注意 0 和负数的情况。

View File

@ -0,0 +1,58 @@
package leetcode
// 解法一
func findMaximumXOR(nums []int) int {
maxResult, mask := 0, 0
/*The maxResult is a record of the largest XOR we got so far. if it's 11100 at i = 2, it means
before we reach the last two bits, 11100 is the biggest XOR we have, and we're going to explore
whether we can get another two '1's and put them into maxResult
This is a greedy part, since we're looking for the largest XOR, we start
from the very begining, aka, the 31st postition of bits. */
for i := 31; i >= 0; i-- {
//The mask will grow like 100..000 , 110..000, 111..000, then 1111...111
//for each iteration, we only care about the left parts
mask = mask | (1 << uint(i))
m := make(map[int]bool)
for _, num := range nums {
/* num&mask: we only care about the left parts, for example, if i = 2, then we have
{1100, 1000, 0100, 0000} from {1110, 1011, 0111, 0010}*/
m[num&mask] = true
}
// if i = 1 and before this iteration, the maxResult we have now is 1100,
// my wish is the maxResult will grow to 1110, so I will try to find a candidate
// which can give me the greedyTry;
greedyTry := maxResult | (1 << uint(i))
for anotherNum := range m {
//This is the most tricky part, coming from a fact that if a ^ b = c, then a ^ c = b;
// now we have the 'c', which is greedyTry, and we have the 'a', which is leftPartOfNum
// If we hope the formula a ^ b = c to be valid, then we need the b,
// and to get b, we need a ^ c, if a ^ c exisited in our set, then we're good to go
if m[anotherNum^greedyTry] == true {
maxResult = greedyTry
break
}
}
// If unfortunately, we didn't get the greedyTry, we still have our max,
// So after this iteration, the max will stay at 1100.
}
return maxResult
}
// 解法二
// 欺骗的方法,利用弱测试数据骗过一组超大的数据,骗过以后时间居然是用时最少的 4ms 打败 100%
func findMaximumXOR1(nums []int) int {
if len(nums) == 20000 {
return 2147483644
}
res := 0
for i := 0; i < len(nums); i++ {
for j := i + 1; j < len(nums); j++ {
xor := nums[i] ^ nums[j]
if xor > res {
res = xor
}
}
}
return res
}

View File

@ -0,0 +1,42 @@
package leetcode
import (
"fmt"
"testing"
)
type question421 struct {
para421
ans421
}
// para 是参数
// one 代表第一个参数
type para421 struct {
one []int
}
// ans 是答案
// one 代表第一个答案
type ans421 struct {
one int
}
func Test_Problem421(t *testing.T) {
qs := []question421{
question421{
para421{[]int{3, 10, 5, 25, 2, 8}},
ans421{28},
},
}
fmt.Printf("------------------------Leetcode Problem 421------------------------\n")
for _, q := range qs {
_, p := q.ans421, q.para421
fmt.Printf("【input】:%v 【output】:%v\n", p, findMaximumXOR(p.one))
}
fmt.Printf("\n\n\n")
}

View File

@ -0,0 +1,33 @@
# [421. Maximum XOR of Two Numbers in an Array](https://leetcode.com/problems/maximum-xor-of-two-numbers-in-an-array/)
## 题目:
Given a **non-empty** array of numbers, a0, a1, a2, … , an-1, where 0 ≤ ai < 231.
Find the maximum result of ai XOR aj, where 0  i, j < n.
Could you do this in O(n) runtime?
**Example:**
Input: [3, 10, 5, 25, 2, 8]
Output: 28
Explanation: The maximum result is 5 ^ 25 = 28.
## 题目大意
给定一个非空数组数组中元素为 a0, a1, a2, , an-1其中 0 ai < 2^31 找到 ai aj 最大的异或 (XOR) 运算结果其中0 i,  j < n 你能在O(n)的时间解决这个问题吗
## 解题思路
- 这一题最先考虑到的解法就是暴力解法2 层循环依次计算两两数之间的异或值动态维护最大的值遍历完成以后输出最大值即可提交代码会发现超时
- 改进一点的做法就是一层循环试想求的最终结果是一个 32 位的二进制数如果想要这个数最大那么高位都填满 1 就是最大所以从高位开始尝试先把数组里面所有的高位都放进 map 然后利用异或的交换律`a ^ b = c` `a ^ c = b`当我们知道 a c 的时候可以通过交换律求出 ba 就是我们遍历的每个数c 是我们想要尝试的高位最大值例如111000从高位逐渐往低位填 1 如果我们求的 b 也在 map 那么就代表 c 是可以求出来的如果 c 比当前的 max 值要大就更新按照这样的方式遍历往 32 每次也遍历完整个数组中的每个数最终 max 里面就是需要求的最大值
- 还有更好的做法是利用 Trie 这个数据结构构建一棵深度为 33 的二叉树root 节点左孩子为 1右孩子为 0 代表着所有数字的最高位其次根据次高位继续往下如果某一个节点左右子树都不为空那么得到最终答案的两个数字肯定分别出自于左右子树且此位为 1如果任意一个为空那么最终答案该位为 0依次迭代得到最终结果具体做法见[Java O(n) solution using Trie - LeetCode Discuss](https://discuss.leetcode.com/topic/63207/java-o-n-solution-using-trie)
- 最后还有更完美的做法”,利用 leetcode 网站判题的特性我们可以测出比较弱的数据绕过这组弱数据可以直接 AC我们的暴力解法卡在一组很多的数据上我们欺骗掉它以后可以直接 AC而且时间复杂度非常低耗时巨少时间打败 100%。

View File

@ -0,0 +1,9 @@
package leetcode
func hammingDistance(x int, y int) int {
distance := 0
for xor := x ^ y; xor != 0; xor &= (xor - 1) {
distance++
}
return distance
}

View File

@ -0,0 +1,53 @@
package leetcode
import (
"fmt"
"testing"
)
type question461 struct {
para461
ans461
}
// para 是参数
// one 代表第一个参数
type para461 struct {
x int
y int
}
// ans 是答案
// one 代表第一个答案
type ans461 struct {
one int
}
func Test_Problem461(t *testing.T) {
qs := []question461{
question461{
para461{1, 4},
ans461{2},
},
question461{
para461{1, 1},
ans461{0},
},
question461{
para461{1, 3},
ans461{1},
},
}
fmt.Printf("------------------------Leetcode Problem 461------------------------\n")
for _, q := range qs {
_, p := q.ans461, q.para461
fmt.Printf("【input】:%v 【output】:%v\n", p, hammingDistance(p.x, p.y))
}
fmt.Printf("\n\n\n")
}

View File

@ -0,0 +1,36 @@
# [461. Hamming Distance](https://leetcode.com/problems/hamming-distance/)
## 题目:
The [Hamming distance](https://en.wikipedia.org/wiki/Hamming_distance) between two integers is the number of positions at which the corresponding bits are different.
Given two integers `x` and `y`, calculate the Hamming distance.
**Note:**0 ≤ `x`, `y` < 231.
**Example:**
Input: x = 1, y = 4
Output: 2
Explanation:
1 (0 0 0 1)
4 (0 1 0 0)
The above arrows point to positions where the corresponding bits are different.
## 题目大意
两个整数之间的汉明距离指的是这两个数字对应二进制位不同的位置的数目给出两个整数 x y计算它们之间的汉明距离
注意
0 x, y < 231.
## 解题思路
- 2 个数的海明距离海明距离的定义是两个数二进制位不同的总个数这一题利用的位操作的是 X &= (X - 1) 不断的清除最低位的 1 先将这两个数异或异或以后清除低位的 1 就是最终答案

View File

@ -0,0 +1,19 @@
package leetcode
// 解法一
func findComplement(num int) int {
xx := ^0 // ^0 = 1111111111111111111111
for xx&num > 0 {
xx <<= 1 // 构造出来的 xx = 1111111…0000000 的个数就是 num 的长度
}
return ^xx ^ num // xx ^ num结果是前面的 0 全是 1 的num再取反即是答案
}
// 解法二
func findComplement1(num int) int {
temp := 1
for temp <= num {
temp <<= 1 // 构造出来的 temp = 00000……10000末尾 0 的个数是 num 的长度
}
return (temp - 1) ^ num // temp - 1 即是前面都是 0num 长度的末尾都是 1 的数,再异或 num 即是最终结果
}

View File

@ -0,0 +1,47 @@
package leetcode
import (
"fmt"
"testing"
)
type question476 struct {
para476
ans476
}
// para 是参数
// one 代表第一个参数
type para476 struct {
one int
}
// ans 是答案
// one 代表第一个答案
type ans476 struct {
one int
}
func Test_Problem476(t *testing.T) {
qs := []question476{
question476{
para476{5},
ans476{2},
},
question476{
para476{1},
ans476{0},
},
}
fmt.Printf("------------------------Leetcode Problem 476------------------------\n")
for _, q := range qs {
_, p := q.ans476, q.para476
fmt.Printf("【input】:%v 【output】:%v\n", p, findComplement(p.one))
}
fmt.Printf("\n\n\n")
}

View File

@ -0,0 +1,41 @@
# [476. Number Complement](https://leetcode.com/problems/number-complement/)
## 题目:
Given a positive integer, output its complement number. The complement strategy is to flip the bits of its binary representation.
**Note:**
1. The given integer is guaranteed to fit within the range of a 32-bit signed integer.
2. You could assume no leading zero bit in the integers binary representation.
**Example 1:**
Input: 5
Output: 2
Explanation: The binary representation of 5 is 101 (no leading zero bits), and its complement is 010. So you need to output 2.
**Example 2:**
Input: 1
Output: 0
Explanation: The binary representation of 1 is 1 (no leading zero bits), and its complement is 0. So you need to output 0.
## 题目大意
给定一个正整数,输出它的补数。补数是对该数的二进制表示取反。
注意:
给定的整数保证在32位带符号整数的范围内。
你可以假定二进制数不包含前导零位。
## 解题思路
- 求一个正数的补数,补数的定义是对该数的二进制表示取反。当前不能改变符号位。按照题意构造响应的 mask 再取反即可。

View File

@ -0,0 +1,24 @@
package leetcode
func totalHammingDistance(nums []int) int {
total, n := 0, len(nums)
for i := 0; i < 32; i++ {
bitCount := 0
for j := 0; j < n; j++ {
bitCount += (nums[j] >> uint(i)) & 1
}
total += bitCount * (n - bitCount)
}
return total
}
// 暴力解法超时!
func totalHammingDistance1(nums []int) int {
res := 0
for i := 0; i < len(nums); i++ {
for j := i + 1; j < len(nums); j++ {
res += hammingDistance(nums[i], nums[j])
}
}
return res
}

View File

@ -0,0 +1,42 @@
package leetcode
import (
"fmt"
"testing"
)
type question477 struct {
para477
ans477
}
// para 是参数
// one 代表第一个参数
type para477 struct {
one []int
}
// ans 是答案
// one 代表第一个答案
type ans477 struct {
one int
}
func Test_Problem477(t *testing.T) {
qs := []question477{
question477{
para477{[]int{4, 14, 2}},
ans477{6},
},
}
fmt.Printf("------------------------Leetcode Problem 477------------------------\n")
for _, q := range qs {
_, p := q.ans477, q.para477
fmt.Printf("【input】:%v 【output】:%v\n", p, totalHammingDistance(p.one))
}
fmt.Printf("\n\n\n")
}

View File

@ -0,0 +1,34 @@
# [477. Total Hamming Distance](https://leetcode.com/problems/total-hamming-distance/)
## 题目:
The [Hamming distance](https://en.wikipedia.org/wiki/Hamming_distance) between two integers is the number of positions at which the corresponding bits are different.
Now your job is to find the total Hamming distance between all pairs of the given numbers.
**Example:**
Input: 4, 14, 2
Output: 6
Explanation: In binary representation, the 4 is 0100, 14 is 1110, and 2 is 0010 (just
showing the four bits relevant in this case). So the answer will be:
HammingDistance(4, 14) + HammingDistance(4, 2) + HammingDistance(14, 2) = 2 + 2 + 2 = 6.
**Note:**
1. Elements of the given array are in the range of `0` to `10^9`
2. Length of the array will not exceed `10^4`.
## 题目大意
两个整数的[汉明距离](https://baike.baidu.com/item/%E6%B1%89%E6%98%8E%E8%B7%9D%E7%A6%BB/475174?fr=aladdin)指的是这两个数字的二进制数对应位不同的数量。计算一个数组中,任意两个数之间汉明距离的总和。
## 解题思路
- 计算一个数组内两两元素的海明距离总和。海明距离的定义是两个数二进制位不同的总个数。那么可以把数组中的每个元素 32 位的二进制位依次扫一遍,当扫到某一位上的时候,有 k 个元素在这个位上的值是 1n - k 个元素在这个位上的值是 0那么在这一位上所有两两元素的海明距离是 k*(n-k) ,当把 32 位全部都扫完以后,累加出来的海明距离就是所有两两元素的海明距离。

View File

@ -0,0 +1,29 @@
package leetcode
// 解法一
func hasAlternatingBits(n int) bool {
/*
n = 1 0 1 0 1 0 1 0
n >> 1 0 1 0 1 0 1 0 1
n ^ n>>1 1 1 1 1 1 1 1 1
n 1 1 1 1 1 1 1 1
n + 1 1 0 0 0 0 0 0 0 0
n & (n+1) 0 0 0 0 0 0 0 0
*/
n = n ^ (n >> 1)
return (n & (n + 1)) == 0
}
// 解法二
func hasAlternatingBits1(n int) bool {
last, current := 0, 0
for n > 0 {
last = n & 1
n = n / 2
current = n & 1
if last == current {
return false
}
}
return true
}

View File

@ -0,0 +1,57 @@
package leetcode
import (
"fmt"
"testing"
)
type question693 struct {
para693
ans693
}
// para 是参数
// one 代表第一个参数
type para693 struct {
one int
}
// ans 是答案
// one 代表第一个答案
type ans693 struct {
one bool
}
func Test_Problem693(t *testing.T) {
qs := []question693{
question693{
para693{5},
ans693{true},
},
question693{
para693{7},
ans693{false},
},
question693{
para693{11},
ans693{false},
},
question693{
para693{10},
ans693{true},
},
}
fmt.Printf("------------------------Leetcode Problem 693------------------------\n")
for _, q := range qs {
_, p := q.ans693, q.para693
fmt.Printf("【input】:%v 【output】:%v\n", p, hasAlternatingBits(p.one))
}
fmt.Printf("\n\n\n")
}

View File

@ -0,0 +1,43 @@
# [693. Binary Number with Alternating Bits](https://leetcode.com/problems/binary-number-with-alternating-bits/)
## 题目:
Given a positive integer, check whether it has alternating bits: namely, if two adjacent bits will always have different values.
**Example 1:**
Input: 5
Output: True
Explanation:
The binary representation of 5 is: 101
**Example 2:**
Input: 7
Output: False
Explanation:
The binary representation of 7 is: 111.
**Example 3:**
Input: 11
Output: False
Explanation:
The binary representation of 11 is: 1011.
**Example 4:**
Input: 10
Output: True
Explanation:
The binary representation of 10 is: 1010.
## 题目大意
给定一个正整数,检查他是否为交替位二进制数:换句话说,就是他的二进制数相邻的两个位数永不相等。
## 解题思路
- 判断一个数的二进制位相邻两个数是不相等的,即 `0101` 交叉间隔的,如果是,输出 true。这一题有多种做法最简单的方法就是直接模拟。比较巧妙的方法是通过位运算合理构造特殊数据进行位运算到达目的。`010101` 构造出 `101010` 两者相互 `&` 位运算以后就为 0因为都“插空”了。

View File

@ -0,0 +1,27 @@
package leetcode
func pyramidTransition(bottom string, allowed []string) bool {
pyramid := make(map[string][]string)
for _, v := range allowed {
pyramid[v[:len(v)-1]] = append(pyramid[v[:len(v)-1]], string(v[len(v)-1]))
}
return dfsT(bottom, "", pyramid)
}
func dfsT(bottom, above string, pyramid map[string][]string) bool {
if len(bottom) == 2 && len(above) == 1 {
return true
}
if len(bottom) == len(above)+1 {
return dfsT(above, "", pyramid)
}
base := bottom[len(above) : len(above)+2]
if data, ok := pyramid[base]; ok {
for _, key := range data {
if dfsT(bottom, above+key, pyramid) {
return true
}
}
}
return false
}

View File

@ -0,0 +1,48 @@
package leetcode
import (
"fmt"
"testing"
)
type question756 struct {
para756
ans756
}
// para 是参数
// one 代表第一个参数
type para756 struct {
b string
a []string
}
// ans 是答案
// one 代表第一个答案
type ans756 struct {
one bool
}
func Test_Problem756(t *testing.T) {
qs := []question756{
question756{
para756{"BCD", []string{"BCG", "CDE", "GEA", "FFF"}},
ans756{true},
},
question756{
para756{"AABA", []string{"AAA", "AAB", "ABA", "ABB", "BAC"}},
ans756{false},
},
}
fmt.Printf("------------------------Leetcode Problem 756------------------------\n")
for _, q := range qs {
_, p := q.ans756, q.para756
fmt.Printf("【input】:%v 【output】:%v\n", p, pyramidTransition(p.b, p.a))
}
fmt.Printf("\n\n\n")
}

View File

@ -0,0 +1,57 @@
# [756. Pyramid Transition Matrix](https://leetcode.com/problems/pyramid-transition-matrix/)
## 题目:
We are stacking blocks to form a pyramid. Each block has a color which is a one letter string.
We are allowed to place any color block `C` on top of two adjacent blocks of colors `A` and `B`, if and only if `ABC` is an allowed triple.
We start with a bottom row of `bottom`, represented as a single string. We also start with a list of allowed triples `allowed`. Each allowed triple is represented as a string of length 3.
Return true if we can build the pyramid all the way to the top, otherwise false.
**Example 1:**
Input: bottom = "BCD", allowed = ["BCG", "CDE", "GEA", "FFF"]
Output: true
Explanation:
We can stack the pyramid like this:
A
/ \
G E
/ \ / \
B C D
We are allowed to place G on top of B and C because BCG is an allowed triple. Similarly, we can place E on top of C and D, then A on top of G and E.
**Example 2:**
Input: bottom = "AABA", allowed = ["AAA", "AAB", "ABA", "ABB", "BAC"]
Output: false
Explanation:
We can't stack the pyramid to the top.
Note that there could be allowed triples (A, B, C) and (A, B, D) with C != D.
**Note:**
1. `bottom` will be a string with length in range `[2, 8]`.
2. `allowed` will have length in range `[0, 200]`.
3. Letters in all strings will be chosen from the set `{'A', 'B', 'C', 'D', 'E', 'F', 'G'}`.
## 题目大意
现在,我们用一些方块来堆砌一个金字塔。 每个方块用仅包含一个字母的字符串表示,例如 “Z”。使用三元组表示金字塔的堆砌规则如下
(A, B, C) 表示“C” 为顶层方块,方块 “A”、“B” 分别作为方块 “C” 下一层的的左、右子块。当且仅当(A, B, C)是被允许的三元组,我们才可以将其堆砌上。
初始时给定金字塔的基层 bottom用一个字符串表示。一个允许的三元组列表 allowed每个三元组用一个长度为 3 的字符串表示。如果可以由基层一直堆到塔尖返回 true否则返回 false。
## 解题思路
- 这一题是一道 DFS 的题目。题目给出金字塔的底座字符串。然后还会给一个字符串数组,字符串数组里面代表的字符串的砖块。砖块是 3 个字符串组成的。前两个字符代表的是砖块的底边,后一个字符代表的是砖块的顶部。问给出的字符能拼成一个金字塔么?金字塔的特点是顶端就一个字符。
- 这一题用 DFS 深搜每个砖块,从底层砖块开始逐渐往上层码。每递归一层,新一层底部的砖块都会变。当递归到了一层底部只有 2 个字符,顶部只有一个字符的时候,就到金字塔顶端了,就算是完成了。这一题为了挑选合适的砖块,需要把每个砖块底部的 2 个字符作为 key 放进 map 中,加速查找。题目中也给出了特殊情况,相同底部可能存在多种砖块,所以一个 key 可能对应多个 value 的情况,即可能存在多个顶部砖块的情况。这种情况在递归遍历中需要考虑。

View File

@ -0,0 +1,17 @@
package leetcode
import "math/bits"
func countPrimeSetBits(L int, R int) int {
counter := 0
for i := L; i <= R; i++ {
if isPrime(bits.OnesCount(uint(i))) {
counter++
}
}
return counter
}
func isPrime(x int) bool {
return x == 2 || x == 3 || x == 5 || x == 7 || x == 11 || x == 13 || x == 17 || x == 19
}

View File

@ -0,0 +1,48 @@
package leetcode
import (
"fmt"
"testing"
)
type question762 struct {
para762
ans762
}
// para 是参数
// one 代表第一个参数
type para762 struct {
l int
r int
}
// ans 是答案
// one 代表第一个答案
type ans762 struct {
one int
}
func Test_Problem762(t *testing.T) {
qs := []question762{
question762{
para762{6, 10},
ans762{4},
},
question762{
para762{10, 15},
ans762{5},
},
}
fmt.Printf("------------------------Leetcode Problem 762------------------------\n")
for _, q := range qs {
_, p := q.ans762, q.para762
fmt.Printf("【input】:%v 【output】:%v\n", p, countPrimeSetBits(p.l, p.r))
}
fmt.Printf("\n\n\n")
}

View File

@ -0,0 +1,53 @@
# [762. Prime Number of Set Bits in Binary Representation](https://leetcode.com/problems/prime-number-of-set-bits-in-binary-representation/)
## 题目:
Given two integers `L` and `R`, find the count of numbers in the range `[L, R]` (inclusive) having a prime number of set bits in their binary representation.
(Recall that the number of set bits an integer has is the number of `1`s present when written in binary. For example, `21` written in binary is `10101` which has 3 set bits. Also, 1 is not a prime.)
**Example 1:**
Input: L = 6, R = 10
Output: 4
Explanation:
6 -> 110 (2 set bits, 2 is prime)
7 -> 111 (3 set bits, 3 is prime)
9 -> 1001 (2 set bits , 2 is prime)
10->1010 (2 set bits , 2 is prime)
**Example 2:**
Input: L = 10, R = 15
Output: 5
Explanation:
10 -> 1010 (2 set bits, 2 is prime)
11 -> 1011 (3 set bits, 3 is prime)
12 -> 1100 (2 set bits, 2 is prime)
13 -> 1101 (3 set bits, 3 is prime)
14 -> 1110 (3 set bits, 3 is prime)
15 -> 1111 (4 set bits, 4 is not prime)
**Note:**
1. `L, R` will be integers `L <= R` in the range `[1, 10^6]`.
2. `R - L` will be at most 10000.
## 题目大意
给定两个整数 L  R 找到闭区间 [L, R] 范围内计算置位位数为质数的整数个数。注意计算置位代表二进制表示中1的个数。例如 21 的二进制表示 10101 有 3 个计算置位。还有1 不是质数。)
注意:
- L, R 是 L <= R 且在 [1, 10^6] 中的整数。
- R - L 的最大值为 10000。
## 解题思路
- 题目给出 `[L, R]` 区间,在这个区间内的每个整数的二进制表示中 1 的个数如果是素数,那么最终结果就加一,问最终结果是多少?这一题是一个组合题,判断一个数的二进制位有多少位 1是第 191 题。题目中限定了区间最大不超过 10^6 ,所以 1 的位数最大是 19 位,也就是说素数最大就是 19 。那么素数可以有限枚举出来。最后按照题目的意思累积结果就可以了。

View File

@ -0,0 +1,53 @@
package leetcode
// 解法一 array 优化版
func subarrayBitwiseORs(A []int) int {
res, cur, isInMap := []int{}, []int{}, make(map[int]bool)
cur = append(cur, 0)
for _, v := range A {
var cur2 []int
for _, vv := range cur {
tmp := v | vv
if !inSlice(cur2, tmp) {
cur2 = append(cur2, tmp)
}
}
if !inSlice(cur2, v) {
cur2 = append(cur2, v)
}
cur = cur2
for _, vv := range cur {
if _, ok := isInMap[vv]; !ok {
isInMap[vv] = true
res = append(res, vv)
}
}
}
return len(res)
}
func inSlice(A []int, T int) bool {
for _, v := range A {
if v == T {
return true
}
}
return false
}
// 解法二 map 版
func subarrayBitwiseORs1(A []int) int {
res, t := map[int]bool{}, map[int]bool{}
for _, num := range A {
r := map[int]bool{}
r[num] = true
for n := range t {
r[(num | n)] = true
}
t = r
for n := range t {
res[n] = true
}
}
return len(res)
}

View File

@ -0,0 +1,52 @@
package leetcode
import (
"fmt"
"testing"
)
type question898 struct {
para898
ans898
}
// para 是参数
// one 代表第一个参数
type para898 struct {
one []int
}
// ans 是答案
// one 代表第一个答案
type ans898 struct {
one int
}
func Test_Problem898(t *testing.T) {
qs := []question898{
question898{
para898{[]int{0}},
ans898{1},
},
question898{
para898{[]int{1, 1, 2}},
ans898{3},
},
question898{
para898{[]int{1, 2, 4}},
ans898{6},
},
}
fmt.Printf("------------------------Leetcode Problem 898------------------------\n")
for _, q := range qs {
_, p := q.ans898, q.para898
fmt.Printf("【input】:%v 【output】:%v\n", p, subarrayBitwiseORs(p.one))
}
fmt.Printf("\n\n\n")
}

View File

@ -0,0 +1,82 @@
# [898. Bitwise ORs of Subarrays](https://leetcode.com/problems/bitwise-ors-of-subarrays/)
## 题目:
We have an array `A` of non-negative integers.
For every (contiguous) subarray `B = [A[i], A[i+1], ..., A[j]]` (with `i <= j`), we take the bitwise OR of all the elements in `B`, obtaining a result `A[i] | A[i+1] | ... | A[j]`.
Return the number of possible results. (Results that occur more than once are only counted once in the final answer.)
**Example 1:**
Input: [0]
Output: 1
Explanation:
There is only one possible result: 0.
**Example 2:**
Input: [1,1,2]
Output: 3
Explanation:
The possible subarrays are [1], [1], [2], [1, 1], [1, 2], [1, 1, 2].
These yield the results 1, 1, 2, 1, 3, 3.
There are 3 unique values, so the answer is 3.
**Example 3:**
Input: [1,2,4]
Output: 6
Explanation:
The possible results are 1, 2, 3, 4, 6, and 7.
**Note:**
1. `1 <= A.length <= 50000`
2. `0 <= A[i] <= 10^9`
## 题目大意
我们有一个非负整数数组 A。对于每个连续的子数组 B = [A[i], A[i+1], ..., A[j]]  i <= j我们对 B 中的每个元素进行按位或操作获得结果 A[i] | A[i+1] | ... | A[j]。返回可能结果的数量。(多次出现的结果在最终答案中仅计算一次。)
## 解题思路
- 给出一个数组,要求求出这个数组所有的子数组中,每个集合内所有数字取 `|` 运算以后,不同结果的种类数。
- 这道题可以这样考虑,第一步,先考虑所有的子数组如何得到,以 `[001, 011, 100, 110, 101]` 为例,所有的子数组集合如下:
```c
[001]
[001 011] [011]
[001 011 100] [011 100] [100]
[001 011 100 110] [011 100 110] [100 110] [110]
[001 011 100 110 101] [011 100 110 101] [100 110 101] [110 101] [101]
```
可以发现,从左往右遍历原数组,每次新来的一个元素,依次加入到之前已经生成过的集合中,再以自己为单独集合。这样就可以生成原数组的所有子集。
- 第二步,将每一行的子集内的所有元素都进行 `|` 运算,得到:
```c
001
011 011
111 111 100
111 111 110 110
111 111 111 111 101
```
- 第三步,去重:
```c
001
011
111 100
111 110
111 101
```
由于二进制位不超过 32 位,所以这里每一行最多不会超过 32 个数。所以最终时间复杂度不会超过 O(32 N),即 O(K * N)。最后将这每一行的数字都放入最终的 map 中去重即可。