mirror of
https://gitlab.com/game-loader/hugo.git
synced 2025-04-20 05:52:07 +08:00
leetcode update
This commit is contained in:
parent
4d61572fef
commit
464f419600
@ -7086,3 +7086,183 @@ func replaceWords(dictionary []string, sentence string) string {
|
||||
### 总结
|
||||
|
||||
注意直接使用"+"在go中进行字符串连接是非常耗时的, 因此可以将原句子分割后得到字符串数组, 查询是否存在单词的可行前缀并直接替换对应数组中的字符串, 最后再调用strings.Join将数组中的所有字符串使用空格连接, 可以自行测试如果对数组中每个字符串在查找其可行前缀后都使用"+"连接到结果字符串上耗时远远大于这种方案.
|
||||
|
||||
## day103 2024-06-08
|
||||
|
||||
### 523. Continuous Subarray Sum
|
||||
|
||||
Given an integer array nums and an integer k, return true if nums has a good subarray or false otherwise.
|
||||
|
||||
A good subarray is a subarray where:
|
||||
|
||||
its length is at least two, and
|
||||
the sum of the elements of the subarray is a multiple of k.
|
||||
Note that:
|
||||
|
||||
A subarray is a contiguous part of the array.
|
||||
An integer x is a multiple of k if there exists an integer n such that x = n \* k. 0 is always a multiple of k.
|
||||
|
||||

|
||||
|
||||
### 题解
|
||||
|
||||
本题要求连续子数组和为k的倍数, 则实际有影响的为各个位置上的元素对k取模后的余数, 这种求连续子数组和满足某种条件的问题, 常常可以使用前缀和求解. 在这个问题中使用前缀和保存从数组开头到当前位置元素的所有数字对k取模后求和再对k取模的值, 并将对应的值和当前的下标保存到长度为k的数组中, 数组下标表示前缀和(因为最终要对k取模,因此取值范围一定在k以内), 对应的数组位置的值为这个前缀和对应nums数组中的下标. 这种用数组保存的方式比用map来保存要快得多.
|
||||
|
||||
### 代码
|
||||
|
||||
```go
|
||||
func checkSubarraySum(nums []int, k int) bool {
|
||||
prefixsum := map[int]int{}
|
||||
prefixsum[0] = -1
|
||||
sum := 0
|
||||
exist := false
|
||||
val := 0
|
||||
for i,value := range nums{
|
||||
sum = (sum + value) % k
|
||||
val, exist = prefixsum[sum]
|
||||
if !exist{
|
||||
prefixsum[sum] = i
|
||||
}else if i - val > 1{
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
```
|
||||
|
||||
### 总结
|
||||
|
||||
没有注意到k的取值范围, 因为k的取值范围非常大, 使用数组来保存前缀和对应的下标需要开始k大小的数组, 在实践中会导致超出leetcode的内存限制. 因此这里还是要用map来保存前缀和和对应的下标, 但思路仍然是相同的.
|
||||
|
||||
## day104 2024-06-09
|
||||
|
||||
### 974. Subarray Sums Divisible by K
|
||||
|
||||
Given an integer array nums and an integer k, return the number of non-empty subarrays that have a sum divisible by k.
|
||||
|
||||
A subarray is a contiguous part of an array.
|
||||
|
||||

|
||||
|
||||
### 题解
|
||||
|
||||
本题和昨天的题目类似, 通过前缀和相同来得到能被k整除的连续子数组, 注意本题中k的范围为 $10^4$, 因此可以用数组来保存前缀和对k取模后得到某个余数对应的下标位置个数. 后续遇到相同余数在结果中加上之前相同余数的位置个数, 并更新该余数对应的位置个数.
|
||||
|
||||
### 代码
|
||||
|
||||
```go
|
||||
func subarraysDivByK(nums []int, k int) int {
|
||||
remain := make([]int, k)
|
||||
remain[0] = 1
|
||||
sum := 0
|
||||
result := 0
|
||||
for _, value := range nums{
|
||||
sum = ((sum + value)%k + k) % k
|
||||
result += remain[sum]
|
||||
remain[sum]++
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### 总结
|
||||
|
||||
注意对负数取模的处理, 在这里为了将相同余数的位置个数保存到数组中, 要将负数取模后的数转换为正数(如对5取模得-4转换为1, 在求和过程中这二者的效果相同), 先取模再加一个k再取模(如果是正数通过再取模将加上的k消掉)即可
|
||||
|
||||
## day105 2024-06-10
|
||||
|
||||
### 1051. Height Checker
|
||||
|
||||
A school is trying to take an annual photo of all the students. The students are asked to stand in a single file line in non-decreasing order by height. Let this ordering be represented by the integer array expected where expected[i] is the expected height of the ith student in line.
|
||||
|
||||
You are given an integer array heights representing the current order that the students are standing in. Each heights[i] is the height of the ith student in line (0-indexed).
|
||||
|
||||
Return the number of indices where heights[i] != expected[i].
|
||||
|
||||

|
||||
|
||||
### 题解
|
||||
|
||||
本题思路上很简单, 只需将数组复制一份并排序, 再与原数组比较即可. 这里主要意图应该是让你练习一下排序算法, 因此我们手动实现一下归并排序这种比较经典的排序算法. 归并算法是经典的分治法思想, 分治法分为"分"和"治"两部分, 分即将数组一分为二, 治即对于每个子数组进行排序, 最后将排好序的两个子数组合并(归并的"并"). 对于某一类分治法, 其时间复杂度可以使用主定理进行计算(感兴趣可自行了解).
|
||||
|
||||
<https://en.wikipedia.org/wiki/Master_theorem_(analysis_of_algorithms)>
|
||||
|
||||
### 代码
|
||||
|
||||
```go
|
||||
func heightChecker(heights []int) int {
|
||||
length := len(heights)
|
||||
sorted := mergeSort(heights, length)
|
||||
result := 0
|
||||
for i,value := range sorted{
|
||||
if value != heights[i]{
|
||||
result++
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func mergeSort(input []int, length int) []int{
|
||||
if length == 1{
|
||||
return input
|
||||
}else{
|
||||
mid := length / 2
|
||||
left := mergeSort(input[0:mid],mid)
|
||||
right := mergeSort(input[mid:length],length-mid)
|
||||
result := []int{}
|
||||
j := 0
|
||||
for _,value := range right{
|
||||
for j<mid && left[j]<value{
|
||||
result = append(result, left[j])
|
||||
j++
|
||||
}
|
||||
result = append(result, value)
|
||||
}
|
||||
for j<mid{
|
||||
result = append(result, left[j])
|
||||
j++
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## day 106 2024-06-11
|
||||
|
||||
### 1122. Relative Sort Array
|
||||
|
||||
Given two arrays arr1 and arr2, the elements of arr2 are distinct, and all elements in arr2 are also in arr1.
|
||||
|
||||
Sort the elements of arr1 such that the relative ordering of items in arr1 are the same as in arr2. Elements that do not appear in arr2 should be placed at the end of arr1 in ascending order.
|
||||
|
||||

|
||||
|
||||
### 题解
|
||||
|
||||
考虑数组中数字的大小范围在1000以内, 因此直接对数组排序可以使用计数排序算法. 本题中要求将数组1中的数字按照数组2中数字的顺序排序, 这部分也可以使用计数排序的思想, 即统计数组1中各个数的出现次数, 并保存在一个计数数组中, 这个数组中下标i处的值为数字i对应的数组1中出现的次数. 这种用下标指示值, 用元素指示个数的思路在前面的题中也多次出现. 得到计数数组后, 先将数组中包含在arr2的数按照arr2中的顺序放置, 并将对应位置次数归零, 再从头遍历数组, 按升序将其余数字放在末尾即可.
|
||||
|
||||
### 代码
|
||||
|
||||
```go
|
||||
func relativeSortArray(arr1 []int, arr2 []int) []int {
|
||||
count := make([]int, 1001)
|
||||
for _,value := range arr1{
|
||||
count[value]++
|
||||
}
|
||||
result := []int{}
|
||||
for _,value := range arr2{
|
||||
for count[value]>0{
|
||||
result = append(result, value)
|
||||
count[value]--
|
||||
}
|
||||
}
|
||||
for index,value := range count{
|
||||
for value > 0{
|
||||
result = append(result, index)
|
||||
value--
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
```
|
||||
|
Loading…
Reference in New Issue
Block a user