977 有序陣列平方
func sortedSquares(nums []int) []int {
// 思路,最簡單,先平方,再排序
for idx, num := range nums{
nums[idx] = num * num
}
// 插排思想,維護兩個列表,將無序列表元素插入到有序列表合適位置
for i := 1; i < len(nums); i++ { // 此處nums[:i]即我們維護的有序列表
temp := nums[i] // 暫時存放要插入的元素
for j := 0; j < i; j++ {
if nums[j]>nums[i] {// 前面元素小於後面元素,不符合倒敘
// 將有序列表整體平移
for x := i; x > j; x-- {
nums[x] = nums[x-1]
}
nums[j] = temp // 將移出來的空位補充為nums[i] 元素
}
}
}
return nums
}
時間 平方操作n + 插入排序 n^2 = n^2 空間 兩步操作都在原陣列內部進行 所以 1
func sortedSquares(nums []int) []int {
// 思路2 雙指標,雙端指標向中間移動的方法
length := len(nums)
var newli = make([]int, length)
left, right := 0, length - 1
for left <= right { // 此處取整 是因為 我是左閉右臂區間
sqrtl, sqrtr := nums[left] * nums[left],nums[right] * nums[right]
if sqrtl <= sqrtr { // 取更大的元素,放入到新切片的最後段
newli[length-1] = sqrtr
right-- // 右指標已經放入新切片,可以移動
}else{
newli[length-1] = sqrtl
left++
}
length-- // 新切片指標往前移動一位
}
return newli
}
時間 往左和往右共遍歷n次,所以n 空間 新切片長度n 所以n
209 長度最小子陣列
// 題目真他媽坑,錯略的看我還以為是非連續的子陣列,但是時間上後面的變數說明是連續的,為什麼不他媽的直接在題目上說連續
func minSubArrayLen(target int, nums []int) int {
// 思路: 分而治之,查詢所有子陣列, 然後判斷子和是否等於val
if sum(nums) < target {
return 0
}
// 如何查詢子陣列,答案是雙指標變種,滑動視窗
var min = len(nums)
for left := 0; left < len(nums); left++{
// 先右指標(快指標)往右側滑動,滑動到底部之後,左側才開始滑動一次
for right := left; right < len(nums); right++ {
if sum(nums[left: right+1]) >= target{
if right+1-left < min {
min = right+1-left
}
}
}
}
return min
}
func sum(slice []int) int {
var sum int
for _, val := range slice {
sum += val
}
return sum
}
時間 n*n 空間 1
繃不住了,暴力破解現在會超時了
func minSubArrayLen(target int, nums []int) int {
// 思路: 分而治之,查詢所有子陣列, 然後判斷子和是否等於val
if sum(nums) < target {
return 0
}
// 真滑動視窗, 原理: right是視窗的末端,我們每次計算之前的視窗的和,如果和大於tar, 那麼縮小視窗,即起始位置後移一位,直到大於為止
var min, sum, left = len(nums), 0, 0
for right:=0; right<len(nums); right++{
sum += nums[right]
for (sum >= target) { // 視窗區間和大於 tar 左指標右移動,操~~ 這裡寫成了if然我扣半天
// 更新最小值
if right + 1 - left < min {
min = right + 1 - left
}
sum -= nums[left]
left++
}
}
return min
}
時間 最壞情況是 [2,3,4,5], 1 外層走一次,內層走一次,所以n 空間 1
59 螺旋矩陣
func generateMatrix(n int) [][]int {
// 思考,本質上n*n正方形,所以需要轉n/2(偶數) 或者n/2+1(奇數)圈,原理就是每次遍歷一圈,邊長-2,所以要減去多少個2,就要多少圈,所以是n/2
startx, starty := 0,0 // x y 軸座標
offset, count := 1, 0 // 邊界條件,座標值
var li [][]int
for i:=0; i<n; i++ {
// 初始化多為切片
li = append(li, make([]int, n)) // append會幫助我初始化外層切片,make初始化內層切片
}
for i:=0; i<n/2; i++{
// 轉圈的結構程式碼
// 第一條邊, 左閉右開
var x, y int
for y=starty; y<n-offset; y++{
count++
li[startx][y] = count
}
// 第二條邊
for x=startx; x<n-offset; x++{
count++
li[x][y] = count // const x = n-offset
}
// 三
for y=n-offset; y>offset-1; y--{
count++
li[x][y] = count // const y = n-offset
}
// 四
for x=n-offset; x>offset-1; x--{
count++
li[x][y] = count
}
// 此處的三個變數都可以簡化為 i+1 或者 i+2
startx++
starty++
offset++
}
if n%2 == 1 { // 奇數邊最後一個元素放到中間
count++
li[n/2][n/2] = count
}
return li
}
時間 初始化矩陣n*make n = n^2 + (4*(n-1)+4*(n-3) + ...) 等差數列求和 n^2 == n^2 空間 多維矩陣n^2