程式碼隨想錄演算法訓練營第二天| 977 有序陣列平方 209 長度最小子陣列 59 螺旋矩陣

周公瑾55發表於2024-07-18

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

相關文章