9.1完成任务
1、Leetcode算法题把数组部分刷完了,明天开始链表部分。(其实数组部分的方法要么就考察数学思想,要么双指针,要么滑动窗口,不难)
2、综设课上,对serverless有了一定基础的了解,接下来的两周估计还要学一下这方面的知识
3、go语言之旅的基础又过完了一遍,明天可以开始过包、变量和函数了
4、早上开摆了,没听听力,悲
代码随想录 --数组(二分查找)
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
示例 1:
输入: nums = [-1,0,3,5,9,12], target = 9 输出: 4 解释: 9 出现在 nums 中并且下标为 4
示例 2:
输入: nums = [-1,0,3,5,9,12], target = 2 输出: -1 解释: 2 不存在 nums 中因此返回 -1
for range 相关
首先来个例题方便理解。
package main
import "fmt"
func main() {
map1 := make(map[int]float32)
map1[1] = 1.0
map1[2] = 2.0
map1[3] = 3.0
map1[4] = 4.0
// 读取 key 和 value
for key, value := range map1 {
fmt.Printf("key is: %d - value is: %f\n", key, value)
}
// 读取 key
for key := range map1 {
fmt.Printf("key is: %d\n", key)
}
// 读取 value
for _, value := range map1 {
fmt.Printf("value is: %f\n", value)
}
}
这段代码是在菜鸟教程上面看到的,说输出是
key is: 4 - value is: 4.000000
key is: 1 - value is: 1.000000
key is: 2 - value is: 2.000000
key is: 3 - value is: 3.000000
key is: 1
key is: 2
key is: 3
key is: 4
value is: 1.000000
value is: 2.000000
value is: 3.000000
value is: 4.000000
嘶,开始好奇,为啥前面的key不是按1234来排序的呢。
于是在自己的goland上面复制代码跑了一下,
重复跑了几次,没有一次有相同的结果。
原因是什么呢?
在 Go 中,map 是一个无序的数据结构,这意味着 map 中的键值对没有固定的顺序。因此,当迭代一个 map 时,不能保证迭代的顺序会是相同的。这就是每次运行都得到不同答案的原因。
尽管添加键值对的顺序是固定的(1、2、3、4),但在 map 内部,这些键值对的存储和迭代顺序是不确定的。因此,第一个 for 循环中的键值对可能会以不同的顺序出现,导致不同的输出结果。
原来是map的原因哇。所以想要按照顺序来进行排序,必须首先将键(或值)排序,然后再进行迭代。
代码如下:
package main
import (
"fmt"
"sort"
)
func main() {
map1 := make(map[int]float32)
map1[1] = 1.0
map1[2] = 2.0
map1[3] = 3.0
map1[4] = 4.0
// 获取所有键并排序
keys := make([]int, 0, len(map1))
for key := range map1 {
keys = append(keys, key)
}
sort.Ints(keys)
// 按键的升序顺序迭代 map
for _, key := range keys {
value := map1[key]
fmt.Printf("key is: %d - value is: %f\n", key, value)
}
}
咳咳,扯远了,到map有关的了。
回到for range来
当使用 for range 迭代一个切片时,range 返回两个值:索引和元素值。如果希望查找目标值并返回其索引。可以使用 for range 迭代切片,但要注意 for range 中的索引是数组的索引,而不是数组的值。
代码如下:
func search(nums []int, target int) int {
for i,num :=range nums{//此时i代表的是所对应值的索引,num代表的是元素值
if num==target{
return i
}
}
return -1
}
显然可以发现 nums[i]=num, 所以也可以写成如下形式
func search(nums []int, target int) int {
for i,_ :=range nums{
if nums[i]==target{
return i
}
}
return -1
}
OK,现在for range 弄清楚了,回到题目中来,此题好歹也是一个二分查找,直接遍历找完也太蠢了。
二分查找
实现代码如下,大概思想就是,设头尾俩个指针,然后由于数组已经升序处理了,就取中间数查看与目标数的大小关系,如果小,就把该数左边的数设为右指针。大,同理
func search(nums []int, target int) int {
left, right := 0, len(nums) - 1
for left <= right {
m := left + (right - left) / 2
if nums[m] > target {
right = m - 1
} else if nums[m] < target {
left = m + 1
} else {
return m
}
}
return -1
}
代码随想录 --数组(有序数组的平方)
给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
示例 1:
输入:nums = [-4,-1,0,3,10] 输出:[0,1,9,16,100] 解释:平方后,数组变为 [16,1,0,9,100] 排序后,数组变为 [0,1,9,16,100]
示例 2:
输入:nums = [-7,-3,2,3,11] 输出:[4,9,9,49,121]
思路
拿到此题,首先想到的就是创造一个新数组来存储这些平方后的元素,然后再使用排序算法来进行排序即可。(此种方法时间复杂度挺高的)
代码如下:
func sortedSquares(nums []int) []int {
news := make([]int,len(nums))
for i,_ := range nums{
news[i]=nums[i]*nums[i]
}
sort.Ints(news)
return news
}
但是呢,很明显有着效率更高的解决方法。 首先最大的平方值肯定是在两侧找到,最小的平方值肯定在中间。此题我们就先用最大往里面找吧。最大的就放在新数组最后面。
代码如下
func sortedSquares(nums []int) []int {
news := make([]int,len(nums))
left :=0
right :=len(nums)-1
i :=len(nums)
for left<=right{
if nums[left]*nums[left]>=nums[right]*nums[right]{
news[i-1]=nums[left]*nums[left]
left++
i--
}else{
news[i-1]=nums[right]*nums[right]
right--
i--
}
}
return news
}
题目很简单。看了题解和我的方法一样,继续~
代码随想录 --数组(长度最小的子数组)
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
示例 1:
输入:target = 7, nums = [2,3,1,2,4,3] 输出:2 解释:子数组 [4,3] 是该条件下的长度最小的子数组。
示例 2:
输入:target = 4, nums = [1,4,4] 输出:1
示例 3:
输入:target = 11, nums = [1,1,1,1,1,1,1,1] 输出:0
思路
本来第一眼看到最少以为是要贪心,然后发现题目要求连续,看来是滑动窗口。
代码如下:
func minSubArrayLen(target int, nums []int) int {
left := 0
right :=len(nums)
sum:=0
length := right+1
for i:=0;i<len(nums);i++{
sum+=nums[i]
for sum>=target{
sublength := i-left+1
if sublength<length{
length=sublength
}
sum-=nums[left]
left++
}
}
if length== right+1{
return 0
}else{
return length
}
}
可以理解为左右指针中间窗口的sum为两指针的“共同财产”,就是右指针一直在努力工作挣钱,好不容易共同财产大过target,记录一下两指针之间的距离,结果左指针就开始得瑟挥霍,不停花钱(往右移动),结果花钱一直花到sum又小过target,此时右指针不得不再次出来工作,不停向右移动,周而复始,最后取左右指针离得最近的时候。
做的此种方法复杂度是最低的,就没有再细看官方的解答了。
代码随想录 --数组(螺旋矩阵II)
数组专栏里面最后一题~~
给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
示例 1:
输入:n = 3 输出:[[1,2,3],[8,9,4],[7,6,5]]
示例 2: 输入:n = 1 输出:[[1]]
思路
有一说一,刚拿到题,确实懵掉了(主要没想起来go语言的二维数组咋写,C语言到知道)
然后就先考虑怎么实现把。
第一个例题的图其实可以用来进行拆分。首先将1,2放在一起 34放在一起等等 (其实就是每一个方向n-1个数)。这样保证每一个方向的数的个数是相同的。然后最外面一层走完以后,到里面 其实就是一个方向还剩下n-2个数。
思路差不多理清楚了(这样对边界的判断会好写一点)
然后就是代码实现。
首先肯定要设置四个变量代表上下左右。分别设为0,n-1,0,n-1。然后设置一个num,来统计我们填了多少个数,以及一个max,设置为需要填写的数的个数。以及最后还有一个二维数组array来存储数据
代码如下:
func generateMatrix(n int) [][]int {
top, bottom := 0, n-1
left, right := 0, n-1
max := n * n
num :=1
array := make([][]int, n)
for i := 0; i < n; i++ {
array[i] = make([]int, n)
}
for num <= max {
for i := left; i <= right; i++ {
array[top][i] = num
num++
}
top++//其实就是最上面往里面缩了一行
for i := top; i <= bottom; i++ {
array[i][right] = num
num++
}
right--
for i := right; i >= left; i-- {
array[bottom][i] = num
num++
}
bottom--
for i := bottom; i >= top; i-- {
array[i][left] = num
num++
}
left++
}
return array
}
代码解释: 这一块是二维数组的初始化!,真忘了,得多用用。
array := make([][]int, n)
for i := 0; i < n; i++ {
array[i] = make([]int, n)
}
总结
其实这个题目主要和数学思维有关吧,如果开始分类没分好,感觉会被边界判断折磨,其实整体代码实现并不难,主要是二维数组的初始化忘了,悲。