最接近的三数之和 最接近的三数之和
解题思路 首先对数组进行排序 ,接着遍历数组,用两个指针 分别记录nums[i]
之后的左右边界,令sum = nums[i]+nums[left]+nums[right]
:
若sum<target
,说明三数之和过小,left++
若sum>target
,说明三数之和过大,right--
解题代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 func threeSumClosest (nums []int , target int ) int { sort.Ints(nums) closestSum := nums[0 ]+nums[1 ]+nums[len (nums)-1 ] for i := 0 ; i < len (nums); i++ { left, right := i+1 , len (nums)-1 for left < right { sum := nums[i]+nums[left]+nums[right] if sum == target { return target } else { if abs(target-sum) < abs(target-closestSum) { closestSum = sum } if sum < target { left++ } else { right-- } } } } return closestSum } func abs (n int ) int { if n > 0 { return n } return -n }
位1的个数 位1的个数
解题思路
进行32次移位 ,循环检查给定整数n的二进制位的每一位是否为1
n & (n−1)
,其运算结果恰为把n的二进制位中的最低位的1变为0 的结果。不断让当前的n与n-1做与运算,直到n变为0即可。因为每次运算会使得n的的最低位的1被翻转,因此运算次数就等于n的二进制1的个数。
解题代码
32次移位
1 2 3 4 5 6 7 8 9 10 func hammingWeight (num uint32 ) int { count := 0 for i := 0 ; i <= 32 ; i++ { if num>>i & 1 == 1 { count++ } } return count }
n & (n−1)
运算
1 2 3 4 5 6 7 8 9 func hammingWeight (num uint32 ) int { count := 0 for num != 0 { num = num & (num-1 ) count++ } return count }
打家劫舍 II 打家劫舍 II
解题思路 利用动态规划 的思路,定义一维dp
数组,dp[i]
表示偷i
间房子的最大金额。
初始化:没有房子dp[0] = 0
状态转移方程:dp[i] = max(dp[i-1], dp[i-2]+nums[i-1])
,dp[i]
有两种选择,不偷第i-1
间房子(dp[i-1]
)或者偷第i-1
间房子(dp[i-2]+nums[i-1]
)。
遍历两次数组 ,第一次不偷第一间房屋,第二次不偷最后一间房屋,取两次的最大金额即可。需要注意的是nums
长度为1时,需要特殊处理,直接返回nums[0]
。
解题代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 func rob (nums []int ) int { if len (nums) == 1 { return nums[0 ] } res := 0 dp := make ([]int , len (nums)+1 ) dp[0 ] = 0 dp[1 ] = 0 for i := 2 ; i <= len (nums); i++ { dp[i] = max(dp[i-1 ], dp[i-2 ]+nums[i-1 ]) } res = dp[len (nums)] dp[1 ] = nums[0 ] for i := 2 ; i < len (nums); i++ { dp[i] = max(dp[i-1 ], dp[i-2 ]+nums[i-1 ]) } res = max(res, dp[len (nums)-1 ]) return res } func max (n1, n2 int ) int { if n1 > n2 { return n1 } return n2 }
反转字符串中的单词 III 反转字符串中的单词 III
解题思路 从前向后遍历字符串,记录上一个空格的位置(第一个单词之前的看作-1
)、当前空格的位置(最后一个单词之后的看作len(s)
),反转上一个空格和当前空格之间的单词。
解题代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 func reverseWords (s string ) string { pre, cur := -1 , 0 slice := []byte (s) for cur <= len (slice) { if cur == len (slice) || slice[cur] == ' ' { left, right := pre+1 , cur-1 for left < right { slice[left], slice[right] = slice[right], slice[left] left++ right-- } pre = cur } cur++ } return string (slice) }
在排序数组中查找数字 I 在排序数组中查找数字 I
解题思路 基于二分查找 ,找到最靠前的target
位置。
解题代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 func search (nums []int , target int ) int { left, right := 0 , len (nums)-1 for left < right { mid := (left+right)/2 if nums[mid] < target { left = mid+1 } else { right = mid } } count := 0 for i := left; i < len (nums) && nums[i] == target; i++ { count++ } return count }
有效的字母异位词 有效的字母异位词
解题思路 若字符串s
和t
的长度不相同,肯定不是字母异位词。若长度相同,利用哈希表 ,记录字符串s
中各个字符出现的次数;遍历t
,令hashMap[t[i]]--
,若出现hashMap[t[i]]
小于0
,则t
中存在s
没有的字符
解题代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 func isAnagram (s string , t string ) bool { if len (s) != len (t) { return false } hashMap := make (map [byte ]int , 26 ) for i := 0 ; i < len (s); i++ { hashMap[s[i]]++ } for i := 0 ; i < len (t); i++ { hashMap[t[i]]-- if hashMap[t[i]] < 0 { return false } } return true }