问题一:长度最小的子数组
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0
输入 | 输出 |
target = 7, nums = [2,3,1,2,4,3] | 2 |
target = 4, nums = [1,4,4] | 1 |
思路一:暴力
遍历n*i次数组,分别求每个连续子数组的和,如果大于则记录长度,注意是连续子数组,不是子数组。
思路二:前缀和+二分查找
前缀和保留数组前n项元素的和,则有sum[i-1]+s = x ,二分查找寻找x在sum[i]可能出现的位置,只要位置大于等于0,则说明存在记录下标与i之间的差值。
思路三:滑动窗口
右指针不断往前走,直到尽头,同时存储sum,循环判断sum能不能连续消除left指针的元素,如果可以左指针前进,并记录距离,右指针一直前进
代码:
//暴力
func minSubArrayLen(s int, nums []int) int {
n:= len(nums)
ans:=math.MaxInt
for i:=0;i<n;i++{
res:=0
for j:=i;j<n;j++{
res += nums[j]
if res >= s{
ans = min(ans,j-i+1)
break
}
}
}
if ans == math.MaxInt{
return 0
}
return ans
}
//前缀和
func minSubArrayLen(s int, nums []int) int {
ans := math.MaxInt32
n:= len(nums)
sum:=make([]int,n+1)
for i:=1;i<= n;i++{
sum[i] = nums[i-1] + sum[i-1]
}
for i:=1;i<=n;i++{
bigsum := s+ sum[i-1]
lo := sort.SearchInts(sum,bigsum)
if lo <=n && lo >0{
ans = min(ans,lo -i +1)
}
}
if ans == math.MaxInt32 {
return 0
}
return ans
}
//滑动窗口
func minSubArrayLen(s int, nums []int) int {
n := len(nums)
if n == 0 { return 0}
ans := math.MaxInt32
start, end := 0, 0
sum := 0
for end < n {
sum += nums[end]
for sum >= s {
ans = min(ans, end - start + 1)
sum -= nums[start]
start++
}
end++
}
if ans == math.MaxInt32 {return 0}
return ans
}
func min(x, y int) int {
if x < y {
return x
}
return y
}
问题二:螺旋矩阵 II
给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
输入 | 输出 |
n = 3 | [[1,2,3],[8,9,4],[7,6,5]] |
n = 1 | [[1]] |
思路:两种思路,归根结底,能把一个圈堵住就行
四矢量法:一共四个循环,每次走一个矢量,奇数个的话,中心堵住一个
转圈法: 转圈法的好处在于不需要处理奇数位
代码:
//四矢量法
func generateMatrix(n int) [][]int {
arr := make([][]int, n)
for i := 0; i < n; i++ {
arr[i] = make([]int, n)
}
base_num := 1
left, right := 0, n-1
for left <= right {
for i:=left;i<right;i++{
arr[left][i] = base_num
base_num++
}
for i:=left;i<right;i++{
arr[i][right] =base_num
base_num++
}
for i:=right;i>left;i--{
arr[right][i] =base_num
base_num++
}
for i:= right;i>left;i--{
arr[i][left]= base_num
base_num++
}
left++
right--
}
mid := n/2
if n % 2 == 1{
arr[mid][mid] = base_num;
}
return arr
}
//转圈法
func generateMatrix(n int) [][]int {
arr := make([][]int, n)
for i := 0; i < n; i++ {
arr[i] = make([]int, n)
}
base_num := 1
left, right := 0, n-1
for left <= right {
//从左到右
for i := left; i <= right; i++ {
arr[left][i] = base_num
base_num++
}
//从上到下
for i := left + 1; i <= right; i++ {
arr[i][right] = base_num
base_num++
}
//从右往左
for i := right - 1; i >= left; i-- {
arr[right][i] = base_num
base_num++
}
//从下往上
for i := right - 1; i >= left+1; i-- {
arr[i][left] = base_num
base_num++
}
left++
right--
}
return arr
}
问题三:有序数组的平方
给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序
输入 | 输出 |
nums = [-4,-1,0,3,10] | [0,1,9,16,100] |
nums = [-7,-3,2,3,11] | [4,9,9,49,121] |
思路一:暴力求,平方,排序
思路很简单,遍历数组,Sort.Int排序
思路二:界限双指针
找到负数与非负数之间的界限,然后进行判断,两者较小的元素,然后进入数组
思路三:相向双指针+倒入结果数组
从两头开始找,如果比较这两值的大小,大的进入数组的最后一个元素,并让数组最后指针前移
代码:
//界限双指针
func sortedSquares(nums []int) []int {
n := len(nums)
lastNegIndex := -1
for i := 0; i < n && nums[i] < 0; i++ {
lastNegIndex = i
}
ans := make([]int, 0, n)
for i, j := lastNegIndex, lastNegIndex+1; i >= 0 || j < n; {
if i < 0 {
ans = append(ans, nums[j]*nums[j])
j++
} else if j == n {
ans = append(ans, nums[i]*nums[i])
i--
} else if nums[i]*nums[i] < nums[j]*nums[j] {
ans = append(ans, nums[i]*nums[i])
i--
} else {
ans = append(ans, nums[j]*nums[j])
j++
}
}
return ans
}
//相向双指针
func sortedSquares(nums []int) []int {
n := len(nums)-1
ans := make([]int, len(nums))
lf,ri:=0,len(nums)-1
for lf <= ri{
x,y := nums[lf]*nums[lf],nums[ri]*nums[ri]
if x<y{
ans[n] = y
ri--
}else{
ans[n] = x
lf++
}
n--
}
return ans
}