1. 两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

示例 1:

1
2
3
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

示例 2:

1
2
输入:nums = [3,2,4], target = 6
输出:[1,2]

示例 3:

1
2
输入:nums = [3,3], target = 6
输出:[0,1]

提示:

  • 2 <= nums.length <= 10<sup>4</sup>
  • -10<sup>9</sup> <= nums[i] <= 10<sup>9</sup>
  • -10<sup>9</sup> <= target <= 10<sup>9</sup>
  • 只会存在一个有效答案

进阶:你可以想出一个时间复杂度小于 O(n<sup>2</sup>) 的算法吗?

Solution

1
2
3
4
5
6
7
8
9
10
func twoSum(nums []int, target int) []int {
for i,x := range nums {
for j := i + 1; j < len(nums); j++ {
if x+nums[j] == target {
return []int{i,j}
}
}
}
return nil
}

167. 两数之和 II - 输入有序数组

给定一个已按照非递减顺序排列 的整数数组 numbers ,请你从数组中找出两个数满足相加之和等于目标数 target

函数应该以长度为 2 的整数数组的形式返回这两个数的下标值numbers 的下标 从 1 开始计数 ,所以答案数组应当满足 1 <= answer[0] < answer[1] <= numbers.length

你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素。

示例 1:

1
2
3
输入:numbers = [2,7,11,15], target = 9
输出:[1,2]
解释:2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。

示例 2:

1
2
输入:numbers = [2,3,4], target = 6
输出:[1,3]

示例 3:

1
2
输入:numbers = [-1,0], target = -1
输出:[1,2]

提示:

  • 2 <= numbers.length <= 3 * 10<sup>4</sup>
  • -1000 <= numbers[i] <= 1000
  • numbers非递减顺序 排列
  • -1000 <= target <= 1000
  • 仅存在一个有效答案

Solution

#双指针

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
func twoSum(numbers []int, target int) []int {
left,right := 0, len(numbers) - 1

for left < right {
sum := numbers[left] + numbers [right]
if sum == target {
return []int{left + 1, right + 1}
} else if sum < target {
left++
} else {
right--
}
}
return []int{-1,-1}

}

15. 三数之和

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例 1:

1
2
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]

示例 2:

1
2
输入:nums = []
输出:[]

示例 3:

1
2
输入:nums = [0]
输出:[]

提示:

  • 0 <= nums.length <= 3000
  • -10<sup>5</sup> <= nums[i] <= 10<sup>5</sup>

Solution

#三指针

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
38
39
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> ans;
// 先排序
int n = nums.size();
sort(nums.begin(), nums.end());

// 定义首指针==target
for (int i = 0; i < n; i++) {
if ( i > 0 && nums[i] == nums[i-1])
continue;

int k = n - 1; // 内层首指针
int target = -nums[i];

for (int j = i + 1; j < n; j++) // 内层尾指针
{
if( j > i + 1 && nums[j] == nums[j-1])
continue;

while (j < k && nums[j] + nums[k] > target) { // 遍历尾指针,找合适序列
--k;
}

// 当前i不满足
if(j == k) {
break;
}

// 得到符合条件序列
if(nums[j] + nums[k] == target) {
ans.push_back({nums[i],nums[j],nums[k]});
}
}
}
return ans;
}
};

18. 四数之和

给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):

  • 0 <= a, b, c, d < n
  • abcd 互不相同
  • nums[a] + nums[b] + nums[c] + nums[d] == target

你可以按 任意顺序 返回答案 。

示例 1:

1
2
输入:nums = [1,0,-1,0,-2,2], target = 0
输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]

示例 2:

1
2
输入:nums = [2,2,2,2,2], target = 8
输出:[[2,2,2,2]]

提示:

  • 1 <= nums.length <= 200
  • -10<sup>9</sup> <= nums[i] <= 10<sup>9</sup>
  • -10<sup>9</sup> <= target <= 10<sup>9</sup>

Solution

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> ans;
int n = nums.size();
if(n < 4)
return ans;
sort(nums.begin(), nums.end());

for (int i = 0; i < n - 3; i++) {
if (i > 0 && nums[i] == nums[i-1])
continue;
if ((long) nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target) {
break;
}
if ((long) nums[i] + nums[n - 3] + nums[n - 2] + nums[n - 1] < target) {
continue;
}


for (int j = i + 1; j < n - 2; j++) {
if (j > i + 1 && nums[j] == nums[j-1])
continue;
if ((long) nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target) {
break;
}
if ((long) nums[i] + nums[j] + nums[n - 2] + nums[n - 1] < target) {
continue;
}

// 最内层首尾指针
int m = n - 1, k = j + 1;
while(k < m) {
int sum = nums[i] + nums[j] + nums[k] + nums[m];
if (sum == target) {
ans.push_back({nums[i], nums[j], nums[k], nums[m]});
while (k < m && nums[k] == nums[k + 1]) {
k++;
}
k++;
while (k < m && nums[m] == nums[m - 1]) {
m--;
}
m--;
} else if (sum < target) {
k++;
} else {
m--;
}
}
}
}
return ans;
}
};

509. 斐波那契数

斐波那契数,通常用 F(n) 表示,形成的序列称为 斐波那契数列 。该数列由 01 开始,后面的每一项数字都是前面两项数字的和。也就是:

1
2
F(0) = 0,F(1) = 1
F(n) = F(n - 1) + F(n - 2),其中 n > 1

给你 n ,请计算 F(n)

示例 1:

1
2
3
输入:2
输出:1
解释:F(2) = F(1) + F(0) = 1 + 0 = 1

示例 2:

1
2
3
输入:3
输出:2
解释:F(3) = F(2) + F(1) = 1 + 1 = 2

示例 3:

1
2
3
输入:4
输出:3
解释:F(4) = F(3) + F(2) = 2 + 1 = 3

提示:

  • 0 <= n <= 30

Solution

1
2
3
4
5
6
7
8
9
func fib(n int) int {
if n == 0 {
return 0
} else if n == 1 {
return 1
} else {
return fib(n-2) + fib(n-1)
}
}

70. 爬楼梯

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

注意:给定 n 是一个正整数。

示例 1:

1
2
3
4
5
输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
1\. 1 阶 + 1 阶
2\. 2 阶

示例 2:

1
2
3
4
5
6
输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
1\. 1 阶 + 1 阶 + 1 阶
2\. 1 阶 + 2 阶
3\. 2 阶 + 1 阶

Solution

1
2
3
4
5
6
7
8
9
10
11
12
13
func climbStairs(n int) int {
if n <= 2 {
return n
}
pre1,pre2 := 2,1

for i := 2; i < n; i++ {
cur := pre1 + pre2
pre2 = pre1
pre1 = cur
}
return pre1
}

53. 最大子数组和

给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

子数组 是数组中的一个连续部分。

示例 1:

1
2
3
输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。

示例 2:

1
2
输入:nums = [1]
输出:1

示例 3:

1
2
输入:nums = [5,4,-1,7,8]
输出:23

提示:

  • 1 <= nums.length <= 10<sup>5</sup>
  • -10<sup>4</sup> <= nums[i] <= 10<sup>4</sup>

进阶:如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的 分治法 求解。

Solution

#动态规划

1
2
3
4
5
6
7
8
9
10
11
12
func maxSubArray(nums []int) int {
sum := nums[0]
for i := 1; i < len(nums); i++ {
if nums[i] + nums[i-1] > nums[i] {
nums[i] += nums[i-1]
}
if nums[i] > sum {
sum = nums[i]
}
}
return sum
}

416. 分割等和子集

给你一个 只包含正整数非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。

示例 1:

1
2
3
输入:nums = [1,5,11,5]
输出:true
解释:数组可以分割成 [1, 5, 5] 和 [11] 。

示例 2:

1
2
3
输入:nums = [1,2,3,5]
输出:false
解释:数组不能分割成两个元素和相等的子集。

提示:

  • 1 <= nums.length <= 200
  • 1 <= nums[i] <= 100

Solution

#动态规划 #背包问题 #difficult

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
func canPartition(nums []int) bool {
n := len(nums)
if n < 2 {
return false
}

sum, maxNum := 0,0
for _,num := range nums {
sum += num
if num > maxNum {
maxNum = num
}
}

// 判断总和是不是奇数
if sum%2 != 0 {
return false
}

target := sum / 2
if target < maxNum {
return false
}

dp := make([]bool, target+1)
dp[0] = true
for i := 0; i < n; i++ {
v := nums[i]
for j := target; j >= v; j-- {
dp[j] = dp[j] || dp[j-v]
}
}
return dp[target]

}

322. 零钱兑换

给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。

计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1

你可以认为每种硬币的数量是无限的。

示例 1:

1
2
3
输入:coins = [1, 2, 5], amount = 11
输出:3
解释:11 = 5 + 5 + 1

示例 2:

1
2
输入:coins = [2], amount = 3
输出:-1

示例 3:

1
2
输入:coins = [1], amount = 0
输出:0

示例 4:

1
2
输入:coins = [1], amount = 1
输出:1

示例 5:

1
2
输入:coins = [1], amount = 2
输出:2

提示:

  • 1 <= coins.length <= 12
  • 1 <= coins[i] <= 2<sup>31</sup> - 1
  • 0 <= amount <= 10<sup>4</sup>

Solution

#动态规划

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
func coinChange(coins []int, amount int) int {
dp := make([]int, amount + 1)
dp[0] = 0
// 初始化为math.MaxInt32
for j := 1; j <= amount; j++ {
dp[j] = math.MaxInt32
}
for i := 0; i < len(coins); i++ {
for j := coins[i]; j <= amount ; j++ {
if dp[j-coins[i]] != math.MaxInt32 {
dp[j] = min(dp[j], dp[j-coins[i]]+1)
}
}
}

// 没找到能装满背包的, 就返回-1
if dp[amount] == math.MaxInt32 {
return -1
}
return dp[amount]

}

func min(a, b int) int {
if a < b{
return a
}
return b
}

20. 有效的括号

给定一个只包括 '('')''{''}''['']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。

示例 1:

1
2
输入:s = "()"
输出:true

示例 2:

1
2
输入:s = "()[]{}"
输出:true

示例 3:

1
2
输入:s = "(]"
输出:false

示例 4:

1
2
输入:s = "([)]"
输出:false

示例 5:

1
2
输入:s = "{[]}"
输出:true

提示:

  • 1 <= s.length <= 10<sup>4</sup>
  • s 仅由括号 '()[]{}' 组成

Solution

#栈

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
func isValid(s string) bool {
n := len(s)
if n % 2 == 1 {
return false
}

pairs := map[byte]byte {
')':'(',
']':'[',
'}':'{',
}

stack := []byte{}
for i := 0; i < n; i++ {
if pairs[s[i]] > 0 {
if len(stack) == 0 || stack[len(stack)-1] != pairs[s[i]] {
return false
}
stack = stack[:len(stack)-1]
} else {
stack = append(stack,s[i])
}
}
return len(stack) == 0
}

20. 有效的括号

给定一个只包括 '('')''{''}''['']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。

示例 1:

1
2
输入:s = "()"
输出:true

示例 2:

1
2
输入:s = "()[]{}"
输出:true

示例 3:

1
2
输入:s = "(]"
输出:false

示例 4:

1
2
输入:s = "([)]"
输出:false

示例 5:

1
2
输入:s = "{[]}"
输出:true

提示:

  • 1 <= s.length <= 10<sup>4</sup>
  • s 仅由括号 '()[]{}' 组成

Solution

#栈

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
func isValid(s string) bool {
n := len(s)
if n % 2 == 1 {
return false
}

pairs := map[byte]byte {
')':'(',
']':'[',
'}':'{',
}

stack := []byte{}
for i := 0; i < n; i++ {
if pairs[s[i]] > 0 {
if len(stack) == 0 || stack[len(stack)-1] != pairs[s[i]] {
return false
}
stack = stack[:len(stack)-1]
} else {
stack = append(stack,s[i])
}
}
return len(stack) == 0
}

496. 下一个更大元素 I

nums1 中数字 x下一个更大元素 是指 xnums2 中对应位置 右侧第一个x大的元素。

给你两个 没有重复元素 的数组 nums1nums2 ,下标从 0 开始计数,其中nums1nums2 的子集。

对于每个 0 <= i < nums1.length ,找出满足 nums1[i] == nums2[j] 的下标 j ,并且在 nums2 确定 nums2[j]下一个更大元素 。如果不存在下一个更大元素,那么本次查询的答案是 -1

返回一个长度为 nums1.length 的数组ans作为答案,满足ans[i]是如上所述的 下一个更大元素

示例 1:

1
2
3
4
5
6
输入:nums1 = [4,1,2], nums2 = [1,3,4,2].
输出:[-1,3,-1]
解释:nums1 中每个值的下一个更大元素如下所述:
- 4 ,用加粗斜体标识,nums2 = [1,3,4,2]。不存在下一个更大元素,所以答案是 -1 。
- 1 ,用加粗斜体标识,nums2 = [1,3,4,2]。下一个更大元素是 3 。
- 2 ,用加粗斜体标识,nums2 = [1,3,4,2]。不存在下一个更大元素,所以答案是 -1 。

示例 2:

1
2
3
4
5
输入:nums1 = [2,4], nums2 = [1,2,3,4].
输出:[3,-1]
解释:nums1 中每个值的下一个更大元素如下所述:
- 2 ,用加粗斜体标识,nums2 = [1,2,3,4]。下一个更大元素是 3 。
- 4 ,用加粗斜体标识,nums2 = [1,2,3,4]。不存在下一个更大元素,所以答案是 -1 。

提示:

  • 1 <= nums1.length <= nums2.length <= 1000
  • 0 <= nums1[i], nums2[i] <= 10<sup>4</sup>
  • nums1nums2中所有整数 互不相同
  • nums1 中的所有整数同样出现在 nums2

进阶:你可以设计一个时间复杂度为 O(nums1.length + nums2.length) 的解决方案吗?

Solution

/#暴力解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
func nextGreaterElement(nums1 []int, nums2 []int) []int {
m,n := len(nums1),len(nums2)
res := make([]int, m)
for i := 0; i < m; i++ {
j := 0
for j < n && nums2[j] != nums1[i] {
j++
}
k := j + 1
for k < n && nums2[k] < nums2[j] {
k++
}

if k < n {
res[i] = nums2[k]
} else {
res[i] = -1
}
}
return res

}

456. 132 模式

给你一个整数数组 nums ,数组中共有 n 个整数。132 模式的子序列 由三个整数 nums[i]nums[j]nums[k] 组成,并同时满足:i < j < knums[i] < nums[k] < nums[j]

如果 nums 中存在 132 模式的子序列 ,返回 true ;否则,返回 false

示例 1:

1
2
3
输入:nums = [1,2,3,4]
输出:false
解释:序列中不存在 132 模式的子序列。

示例 2:

1
2
3
输入:nums = [3,1,4,2]
输出:true
解释:序列中有 1 个 132 模式的子序列: [1, 4, 2] 。

示例 3:

1
2
3
输入:nums = [-1,3,2,0]
输出:true
解释:序列中有 3 个 132 模式的的子序列:[-1, 3, 2]、[-1, 3, 0] 和 [-1, 2, 0] 。

提示:

  • n == nums.length
  • 1 <= n <= 2 * 10<sup>5</sup>
  • -10<sup>9</sup> <= nums[i] <= 10<sup>9</sup>

Solution

#栈 #单调栈

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
func find132pattern(nums []int) bool {
n := len(nums)
candidateK := []int{nums[n-1]}

maxK := math.MinInt64

for i := n - 2; i >= 0; i-- {
if nums[i] < maxK {
return true
}

for len(candidateK) > 0 && nums[i] > candidateK[len(candidateK)-1] {
maxK = candidateK[len(candidateK)-1]
candidateK = candidateK[:len(candidateK)-1]
}

if nums[i] > maxK {
candidateK = append(candidateK, nums[i])
}
}
return false
}

119. 杨辉三角 II

给定一个非负索引 rowIndex,返回「杨辉三角」的第 rowIndex行。

在「杨辉三角」中,每个数是它左上方和右上方的数的和。

示例 1:

1
2
输入: rowIndex = 3
输出: [1,3,3,1]

示例 2:

1
2
输入: rowIndex = 0
输出: [1]

示例 3:

1
2
输入: rowIndex = 1
输出: [1,1]

提示:

  • 0 <= rowIndex <= 33

进阶:

你可以优化你的算法到 _O_(_rowIndex_) 空间复杂度吗?

Solution

#数学

1
2
3
4
5
6
7
8
9
10
11
func getRow(rowIndex int) []int {
C := make([][]int, rowIndex+1)
for i := range C {
C[i] = make([]int,i+1)
C[i][0],C[i][i] = 1,1
for j := 1; j < i; j++ {
C[i][j] = C[i-1][j-1] + C[i-1][j]
}
}
return C[rowIndex]
}

279. 完全平方数

给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, ...)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。

给你一个整数 n ,返回和为 n 的完全平方数的 最少数量

完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,14916 都是完全平方数,而 311 不是。

示例 1:

1
2
3
输入:n = 12
输出:3
解释:12 = 4 + 4 + 4

示例 2:

1
2
3
输入:n = 13
输出:2
解释:13 = 4 + 9

提示:

  • 1 <= n <= 10<sup>4</sup>

Solution

#动态规划

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
func numSquares(n int) int {
f := make([]int, n+1)
for i := 1; i <= n; i++ {
minn := math.MaxInt32
for j := 1; j*j <= i; j++ {
minn = min(minn, f[i-j*j])
}
f[i] = minn + 1
}
return f[n]
}

func min(a,b int) int {
if a < b {
return a
}
return b
}


112. 路径总和

给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false

叶子节点 是指没有子节点的节点。

示例 1:

1
2
3
输入:root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
输出:true
解释:等于目标和的根节点到叶节点路径如上图所示。

示例 2:

1
2
3
4
5
6
输入:root = [1,2,3], targetSum = 5
输出:false
解释:树中存在两条根节点到叶子节点的路径:
(1 --> 2): 和为 3
(1 --> 3): 和为 4
不存在 sum = 5 的根节点到叶子节点的路径。

示例 3:

1
2
3
输入:root = [], targetSum = 0
输出:false
解释:由于树是空的,所以不存在根节点到叶子节点的路径。

提示:

  • 树中节点的数目在范围 [0, 5000]
  • -1000 <= Node.val <= 1000
  • -1000 <= targetSum <= 1000

Solution

#广度搜索

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
38
39
40
41
42
43
44
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func hasPathSum(root *TreeNode, targetSum int) bool {
if root == nil {
return false
}

queNode := []*TreeNode{}
queVal := []int{}
queNode = append(queNode,root)
queVal = append(queVal,root.Val)

for len(queNode) != 0 {
now := queNode[0]
queNode = queNode[1:]
temp := queVal[0]
queVal = queVal[1:]

if now.Left == nil && now.Right == nil {
if temp == targetSum {
return true
}
continue
}

if now.Left != nil {
queNode = append(queNode,now.Left)
queVal = append(queVal,now.Left.Val + temp)
}

if now.Right != nil {
queNode = append(queNode, now.Right)
queVal = append(queVal, now.Right.Val + temp)
}
}

return false
}



720. 词典中最长的单词

给出一个字符串数组words组成的一本英语词典。从中找出最长的一个单词,该单词是由words词典中其他单词逐步添加一个字母组成。若其中有多个可行的答案,则返回答案中字典序最小的单词。

若无答案,则返回空字符串。

示例 1:

1
2
3
4
5
输入:
words = ["w","wo","wor","worl", "world"]
输出:"world"
解释:
单词"world"可由"w", "wo", "wor", 和 "worl"添加一个字母组成。

示例 2:

1
2
3
4
5
输入:
words = ["a", "banana", "app", "appl", "ap", "apply", "apple"]
输出:"apple"
解释:
"apply"和"apple"都能由词典中的单词组成。但是"apple"的字典序小于"apply"。

提示:

  • 所有输入的字符串都只包含小写字母。
  • words数组长度范围为[1,1000]
  • words[i]的长度范围为[1,30]

Solution

Language: **

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
func longestWord(words []string) string {
// 排序哈希
sort.Strings(words)

// 字符串/是否出现
wordsMap := make(map[string]bool)
res := ""

for _,word := range words {
wlen, reslen := len(word), len(res)

// 字符串前缀
if wlen == 1 || wordsMap[word[:wlen-1]] {
wordsMap[word] = true
// 更新res为最长的单词
if reslen == 0 || reslen < wlen {
res = word
}
}
}

return res

}


3. 无重复字符的最长子串

给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。

示例 1:

1
2
3
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

示例 2:

1
2
3
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。

示例 3:

1
2
3
4
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

示例 4:

1
2
输入: s = ""
输出: 0

提示:

  • 0 <= s.length <= 5 * 10<sup>4</sup>
  • s 由英文字母、数字、符号和空格组成

Solution

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
func lengthOfLongestSubstring(s string) int {
m := map[byte]int{}
n := len(s)

rk, ans := -1, 0
for i := 0; i < n; i++ {
if i != 0 {
delete(m,s[i-1])
}

for rk + 1 < n && m[s[rk+1]] == 0 {
m[s[rk+1]]++
rk++
}

ans = max(ans, rk - i + 1)
}
return ans
}

func max(x, y int) int {
if x < y {
return y
}
return x
}



28. 实现 strStr()

实现 函数。

给你两个字符串 haystackneedle ,请你在 haystack 字符串中找出 needle 字符串出现的第一个位置(下标从 0 开始)。如果不存在,则返回 -1

说明:

needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。

对于本题而言,当 needle 是空字符串时我们应当返回 0 。这与 C 语言的 以及 Java 的 定义相符。

示例 1:

1
2
输入:haystack = "hello", needle = "ll"
输出:2

示例 2:

1
2
输入:haystack = "aaaaa", needle = "bba"
输出:-1

示例 3:

1
2
输入:haystack = "", needle = ""
输出:0

提示:

  • 0 <= haystack.length, needle.length <= 5 * 10<sup>4</sup>
  • haystackneedle 仅由小写英文字符组成

Solution

1
2
3
4
5
6
7
8
9
10
11
12
13
func strStr(haystack string, needle string) int {
n,m := len(haystack), len(needle)
outer:
for i := 0; i + m <= n; i++ {
for j:= range needle {
if haystack[i+j] != needle[j] {
continue outer
}
}
return i
}
return -1
}

121. 买卖股票的最佳时机

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0

示例 1:

1
2
3
4
输入:[7,1,5,3,6,4]
输出:5
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。

示例 2:

1
2
3
输入:prices = [7,6,4,3,1]
输出:0
解释:在这种情况下, 没有交易完成, 所以最大利润为 0。

提示:

  • 1 <= prices.length <= 10<sup>5</sup>
  • 0 <= prices[i] <= 10<sup>4</sup>

Solution

#贪心

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
func maxProfit(prices []int) (max int) {
min := prices[0]
max = 0
for _,price := range prices {
if price < min {
min = price
} else {
if max > price - min {
continue
} else {
max = price - min
}
}
}
return
}