github.com/qiuhoude/go-web@v0.0.0-20220223060959-ab545e78f20d/algorithm/leetcode/longest-increasing-subsequence_test.go (about) 1 package leetcode 2 3 import "testing" 4 5 //leetcode 300. 最长上升子序列 6 // https://leetcode-cn.com/problems/longest-increasing-subsequence 7 8 /* 9 给定一个无序的整数数组,找到其中最长上升子序列的长度。 10 输入: [10,9,2,5,3,7,101,18] 11 输出: 4 12 解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4。 13 */ 14 15 // 思路: 求出 f(i) = j i表示数值的下表,j表示长度 16 // 当下表为i 时 前面序列的长度 17 // f(0) = 1 10前面没有比他小的 18 // f(1) = 1 9 前面没有比他小的 19 // f(2) = f(1)+1 = 2 20 // f(3) = max(f(0),f(1))+1 21 // db[] 保存的就是 下表为i的时最长子序列长度 22 23 func lengthOfLIS(nums []int) int { 24 dp := make([]int, len(nums)) 25 max := 0 26 for i := 0; i < len(nums); i++ { 27 dp[i] = 1 28 //比较前面i项最大子序列值 29 for j := 0; j < i; j++ { 30 if nums[j] < nums[i] && dp[i] < dp[j]+1 { 31 dp[i] = dp[j] + 1 32 } 33 } 34 if dp[i] > max { 35 max = dp[i] 36 } 37 } 38 return max 39 } 40 41 func lengthOfLIS2(nums []int) int { 42 if len(nums) == 0 { 43 return 0 44 } 45 // tail 数组的定义:长度为 i + 1 的上升子序列的末尾最小是几 46 tail := make([]int, len(nums)) 47 // 遍历第 1 个数,直接放在有序数组 tail 的开头 48 tail[0] = nums[0] 49 // end 表示有序数组 tail 的最后一个已经赋值元素的索引 50 end := 0 51 for i := 1; i < len(nums); i++ { 52 // 【逻辑 1】比 tail 数组实际有效的末尾的那个元素还大 53 if nums[i] > tail[end] { 54 end++ 55 tail[end] = nums[i] 56 } else { 57 // 使用二分查找法,在有序数组 tail 中 58 // 找到第 1 个大于等于 nums[i] 的元素,尝试让那个元素更小 59 left := 0 60 right := left 61 for left < right { 62 // 选左中位数不是偶然,而是有原因的,原因请见 LeetCode 第 35 题题解 63 mid := left + (right-left)/2 64 if tail[mid] < nums[i] { 65 // 中位数肯定不是要找的数,把它写在分支的前面 66 left = mid + 1 67 } else { 68 right = mid 69 } 70 } 71 //走到这里是因为 【逻辑 1】 的反面,因此一定能找到第 1 个大于等于 nums[i] 的元素 72 tail[left] = nums[i] 73 } 74 } 75 end++ 76 return end 77 } 78 79 func TestLengthOfLIS(t *testing.T) { 80 tests := []struct { 81 name string 82 args []int 83 want int 84 }{ 85 {"[10,9,2,5,3,7,101,18] => 4", []int{10, 9, 2, 5, 3, 7, 101, 18}, 4}, 86 {"[10,9,2,5,3,4] => 3", []int{10, 9, 2, 5, 3, 4}, 3}, 87 } 88 for _, tt := range tests { 89 t.Run(tt.name, func(t *testing.T) { 90 if got := lengthOfLIS(tt.args); got != tt.want { 91 t.Errorf("lengthOfLIS() = %v, want %v", got, tt.want) 92 93 } 94 }) 95 } 96 }