目录
977.有序数组的平方 (golang)
给你一个按 非递减顺序 排序的整数数组 nums
,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
思路1:暴力遍历:
遍历整个nums,每个nums[i] = nums[i]*nums[i]。然后排序一下。就是每个数平方之后,排个序。
func sortedSquares(nums []int) []int {
for i:=0;i<len(nums);i++{
nums[i] = nums[i]*nums[i] //数值的值变为其平方后的值
}
sort.Ints(nums) //对数组排序
return nums
}
//这个时间复杂度是 O(n + nlogn), 可以说是O(nlogn)的时间复杂度
思路2:双指针
双指针就是一个在前一个在后。
因为数组其实是有序的, 只不过负数平方之后可能成为最大数了。那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。
此时可以考虑双指针法了,left指向起始位置,right指向终止位置(最后的下标)。
left, right := 0, len(nums)-1
定义一个新数组result,和nums数组一样的大小,让k指向result数组终止位置(最后的下标)。
result := make([]int,len(nums))
k := len(nums)-1
接下来就是比较。比较双指针的大小,也就是比较left下标所对应值的平方和right下标所对应值的平方大小。大的那一个放在result[k]里面。每次放完后k都要--。
定义一个新数组result,和nums数组一样的大小,让k指向result数组终止位置。
如果nums[left] * nums[left] > nums[right] * nums[right]
那么result[k] = nums[left] * nums[left];
k--
如果nums[i] * nums[i]
那么result[k] = nums[right] * nums[right]
k--
func sortedSquares(nums []int) []int {
left, right := 0, len(nums)-1
k := len(nums)-1
result := make([]int,len(nums))
for left <= right { //要小于等于,相等的时候也要取平方然后放进result得啊
if nums[left]*nums[left] > nums[right]*nums[right] {
result[k] = nums[left]*nums[left] //选择大的
k-- //别忘记每次第k个位置填完之后要--
left++ //从左往右移动
} else {
result[k] = nums[right]*nums[right] //选择大的
k--
right-- //从右往左移
}
}
return result //返回新的数组
}
209、长度最小的子数组(golang)
给定一个含有 n 个正整数的数组和一个正整数 target 。找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
分析:暴力解法
本题go用暴力会超时
func minSubArrayLen(target int, nums []int) int {
count := len(nums)+1
for i:=0;i<len(nums);i++{
sum := 0
for j:=i;j<len(nums);j++{
sum += nums[j]
if sum >= target {
count = min(count, j-i+1)
break
}
}
}
if count == len(nums)+1 {
return 0
}
return count
}
func min(a , b int) int {
if a > b {
return b
}
return a
}
分析:滑动窗口
所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。
在暴力解法中,是一个for循环滑动窗口的起始位置,一个for循环为滑动窗口的终止位置,用两个for循环 完成了一个不断搜索区间的过程。
在本题中实现滑动窗口,主要确定如下三点:
- 窗口内是什么?
- 如何移动窗口的起始位置?
- 如何移动窗口的结束位置?
窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。
窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了(也就是该缩小了)。
窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。
go代码如下
func minSubArrayLen(target int, nums []int) int {
left, right := 0,0 //
sum := 0
res := len(nums)+1
for right < len(nums) {
sum += nums[right] // 窗口内。
for sum >= target { //移动窗口起始位置,注意是for不是if。因为可能sum的总和减去左边一次之后还是大于target的,还需要再继续缩短区间啊
res = min(res, right-left+1) //记录当前满足条件的子数组
sum -= nums[left] //你往右移动,左边的就要删掉了。
left++ //往右移动
}
right++ //正常往右移动
}
if res == len(nums)+1 { //如果res 没变过,也就是不存在符合条件的子数组
return 0
}
return res //返回符合条件的子数组长度
}
func min(a, b int) int {
if a > b {
return b
}
return a
}
59.螺旋矩阵II
给定一个正整数 n,生成一个包含 1 到 n^2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。
示例:
输入: 3
输出:
[[ 1, 2, 3 ],
[ 8, 9, 4 ],
[ 7, 6, 5 ] ]
思路:
这一道题主要是模拟。模拟顺时针画矩阵的过程:
- 填充上行从左到右
- 填充右列从上到下
- 填充下行从右到左
- 填充左列从下到上
由外向内一圈一圈这么画下去。
func generateMatrix(n int) [][]int {
//边长与填充数字
top,bottom,left,right := 0,n-1,0,n-1
num := 1
//初始化矩阵
matrix := make([][]int,n)
for i, _ := range matrix {
matrix[i] = make([]int,n)
}
tar := n * n
//开始依次填充
for num <= tar {
for i:=left;i<=right;i++{
matrix[top][i] = num //填充都是某一行的第i列。所以i是列,变的是列
num++
}
top++ //填充完一次top就往下移
for i:=top;i<=bottom;i++{
matrix[i][right] = num //填充的都是某一列的第i行,所以i是行,变的是行
num++
}
right-- //填完一次right就往左边移
for i:=right;i>=left;i--{
matrix[bottom][i] = num //填充的都是某一行的第i列,所以i是列,变的是列
num++
}
bottom-- //填完一次bottom就往上移
for i:=bottom;i>=top;i--{
matrix[i][left] = num //填充的都是某一列的的第i行,所以i是行,变得是行
num++
}
left++ //填完一次left就往右移动
}
return matrix
}