From abb9cfd5be04acf55f41f0438abe43b587354b3e Mon Sep 17 00:00:00 2001 From: liyao <-> Date: Sat, 14 Aug 2021 16:24:20 +0100 Subject: [PATCH 1/6] =?UTF-8?q?=E6=9B=B4=E6=AD=A3=20=E6=9C=80=E9=95=BF?= =?UTF-8?q?=E9=80=92=E5=A2=9E=E5=AD=90=E5=BA=8F=E5=88=97=20=E7=AE=97?= =?UTF-8?q?=E6=B3=95=E5=A4=8D=E6=9D=82=E5=BA=A6=EF=BC=8C=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?O(nlogn)=E6=97=B6=E9=97=B4=E5=A4=8D=E6=9D=82=E5=BA=A6=E7=AE=97?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0300.最长上升子序列.md | 124 ++++++++++++++++++++++++- 1 file changed, 122 insertions(+), 2 deletions(-) diff --git a/problems/0300.最长上升子序列.md b/problems/0300.最长上升子序列.md index 57edd13e..1161e158 100644 --- a/problems/0300.最长上升子序列.md +++ b/problems/0300.最长上升子序列.md @@ -33,7 +33,7 @@ * 1 <= nums.length <= 2500 * -10^4 <= nums[i] <= 104 - +## 方法一 动态规划 ## 思路 最长上升子序列是动规的经典题目,这里dp[i]是可以根据dp[j] (j < i)推导出来的,那么依然用动规五部曲来分析详细一波: @@ -190,10 +190,130 @@ const lengthOfLIS = (nums) => { }; ``` *复杂度分析* -- 时间复杂度:O(nlogn)。数组 nums 的长度为 n,我们依次用数组中的元素去更新 dp 数组,相当于插入最后递增的元素,而更新 dp 数组时需要进行 O(logn) 的二分搜索,所以总时间复杂度为 O(nlogn)。 +- 时间复杂度:O(n^2)。数组 nums 的长度为 n,我们依次用数组中的元素去遍历 dp 数组,而遍历 dp 数组时需要进行 O(n) 次搜索,所以总时间复杂度为 O(n^2)。 - 空间复杂度:O(n),需要额外使用长度为 n 的 dp 数组。 +## 方法二 贪心策略+二分搜索 + +使用贪心策略和二分搜索可以进一步将算法时间复杂度将为O(nlogn)。 + +## 思路 + +为了使得到的子序列尽可能长,我们需要使序列上升得尽可能慢。 + +对于长度为n的数组 nums,我们从0到n-1依次遍历数组中的每个元素nums[i],更新在0到i范围内最长上升子序列的长度len,以及 在0到i范围内,上升子序列的长度为1到len时,对应长度子序列最右端的最小值,将结果保存在list中。实际编码过程中,list长度即为len。 + +## 可行性 +当我们遍历完数组nums中第n-1个元素时,list中保存的是0到n-1范围内最长上升子序列的长度,即为所求。 + +## 算法复杂度分析 +1. list中的元素是单调递增的。可以用反证法来证明:假设对于0<=i=list[j],那么我们可以在list[j]对应的子序列中删除最后j-i个元素得到长度与list[i]相同的子序列,其最右端的值maxlist[len-1],此时,list中子序列长度为1到len的对应的最右端最小值不变,并新增长度为len+1的子序列,最右端的最小值为nums[i],时间复杂度O(1); + + 2. if(nums[i]<=list[len-1]),此时,我们可以在0到len-1范围内找到k,list[k]为>=nums[i]的最小值,由于list单调递增,所以我们可以使用二分搜索在O(logn)的时间复杂度内找到k。 + 1. 对于0<=jnums[i]; + +3. 综上,算法时间复杂度为O(nlogn),空间复杂度为O(n),需要O(n)的空间保存list。 + +代码如下 + +Java +```java +class Solution { + public int lengthOfLIS(int[] nums) { + int n = nums.length; + if(n==0){return 0;} + + List list=new ArrayList<>(); + list.add(nums[0]); + for (int i = 1; i < n; ++i) { + if (nums[i] > list.get(list.size()-1)) { + list.add(nums[i]); + } else { + int k=binarySearch(list,nums[i]); + list.set(k,nums[i]); + } + } + return list.size(); + } + + int binarySearch(Listlist, int num){ + int len=list.size(); + int l=0,r=len-1,ans=len-1; + while(l<=r){ + int mid=l+(r-l)/2; + if(list.get(mid) list[len-1]) { + list[len++]=nums[i]; + } else { + int k=binarySearch(list,len,nums[i]); + list[k]=nums[i]; + } + } + return len; + } + + int binarySearch(int[] list,int len, int num){ + + int l=0,r=len-1,ans=len-1; + while(l<=r){ + int mid=l+(r-l)/2; + if(list[mid] Date: Tue, 17 Aug 2021 12:24:54 +0800 Subject: [PATCH 2/6] =?UTF-8?q?Update=20=E8=83=8C=E5=8C=85=E7=90=86?= =?UTF-8?q?=E8=AE=BA=E5=9F=BA=E7=A1=8001=E8=83=8C=E5=8C=85-1.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修改错别字 --- problems/背包理论基础01背包-1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problems/背包理论基础01背包-1.md b/problems/背包理论基础01背包-1.md index c13efc3a..851c2657 100644 --- a/problems/背包理论基础01背包-1.md +++ b/problems/背包理论基础01背包-1.md @@ -103,7 +103,7 @@ dp[0][j],即:i为0,存放编号0的物品的时候,各个容量的背包 那么很明显当 j < weight[0]的时候,dp[0][j] 应该是 0,因为背包容量比编号0的物品重量还小。 -当j >= weight[0]是,dp[0][j] 应该是value[0],因为背包容量放足够放编号0物品。 +当j >= weight[0]时,dp[0][j] 应该是value[0],因为背包容量放足够放编号0物品。 代码初始化如下: ``` From 07e95e7a97f1bdf55386cbc6c05f6b9cfba88a04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=81=E5=AE=A2=E5=AD=A6=E4=BC=9F?= Date: Mon, 16 Aug 2021 13:00:02 +0800 Subject: [PATCH 3/6] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20203.=E7=A7=BB=E9=99=A4?= =?UTF-8?q?=E9=93=BE=E8=A1=A8=E5=85=83=E7=B4=A0=20Swift=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0203.移除链表元素.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/problems/0203.移除链表元素.md b/problems/0203.移除链表元素.md index 9235d47e..f3724fc2 100644 --- a/problems/0203.移除链表元素.md +++ b/problems/0203.移除链表元素.md @@ -304,8 +304,7 @@ var removeElements = function(head, val) { }; ``` -Swift: - +Swift: ```swift /** * Definition for singly-linked list. From c7c52f7db6d92800a273057c3a5abc4cffcc8aef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=81=E5=AE=A2=E5=AD=A6=E4=BC=9F?= Date: Mon, 16 Aug 2021 20:28:38 +0800 Subject: [PATCH 4/6] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20707.=E8=AE=BE=E8=AE=A1?= =?UTF-8?q?=E9=93=BE=E8=A1=A8=20Swift=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0707.设计链表.md | 64 +++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/problems/0707.设计链表.md b/problems/0707.设计链表.md index 0aa038e8..33b02e56 100644 --- a/problems/0707.设计链表.md +++ b/problems/0707.设计链表.md @@ -948,6 +948,70 @@ class MyLinkedList { } ``` +Swift +```Swift +class MyLinkedList { + var size = 0 + let head: ListNode + + /** Initialize your data structure here. */ + init() { + head = ListNode(-1) + } + + /** Get the value of the index-th node in the linked list. If the index is invalid, return -1. */ + func get(_ index: Int) -> Int { + if size > 0 && index < size { + var tempHead = head + for _ in 0.. size { + return + } + let idx = (index >= 0 ? index : 0) + var tempHead = head + for _ in 0 ..< idx { + tempHead = tempHead.next! + } + let currentNode = tempHead.next + let newNode = ListNode(val, currentNode) + tempHead.next = newNode + size += 1 + } + + /** Delete the index-th node in the linked list, if the index is valid. */ + func deleteAtIndex(_ index: Int) { + if size > 0 && index < size { + var tempHead = head + for _ in 0 ..< index { + tempHead = tempHead.next! + } + tempHead.next = tempHead.next!.next + size -= 1 + } + } +} +``` ----------------------- From 3f45f392f6c0235393171494790b43eea6350e30 Mon Sep 17 00:00:00 2001 From: X-shuffle <53906918+X-shuffle@users.noreply.github.com> Date: Tue, 17 Aug 2021 20:00:20 +0800 Subject: [PATCH 5/6] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=200343.=E6=95=B4?= =?UTF-8?q?=E6=95=B0=E6=8B=86=E5=88=86=20go=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0343.整数拆分.md | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/problems/0343.整数拆分.md b/problems/0343.整数拆分.md index a9c55a85..03b6f0fc 100644 --- a/problems/0343.整数拆分.md +++ b/problems/0343.整数拆分.md @@ -227,7 +227,34 @@ class Solution: return dp[n] ``` Go: - +```golang +func integerBreak(n int) int { + /** + 动态五部曲 + 1.确定dp下标及其含义 + 2.确定递推公式 + 3.确定dp初始化 + 4.确定遍历顺序 + 5.打印dp + **/ + dp:=make([]int,n+1) + dp[1]=1 + dp[2]=1 + for i:=3;ib{ + return a + } + return b +} +``` Javascript: ```Javascript From eaa0504acbdc195c0804ecaebd033528786e7939 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=81=E5=AE=A2=E5=AD=A6=E4=BC=9F?= Date: Wed, 18 Aug 2021 19:47:30 +0800 Subject: [PATCH 6/6] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20206.=E5=8F=8D=E8=BD=AC?= =?UTF-8?q?=E9=93=BE=E8=A1=A8=20Swift=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0206.翻转链表.md | 37 +++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/problems/0206.翻转链表.md b/problems/0206.翻转链表.md index 8bb359bd..0c850d52 100644 --- a/problems/0206.翻转链表.md +++ b/problems/0206.翻转链表.md @@ -334,6 +334,43 @@ fun reverseList(head: ListNode?): ListNode? { } ``` +Swift: +```swift +/// 双指针法 (迭代) +/// - Parameter head: 头结点 +/// - Returns: 翻转后的链表头结点 +func reverseList(_ head: ListNode?) -> ListNode? { + if head == nil || head?.next == nil { + return head + } + var pre: ListNode? = nil + var cur: ListNode? = head + var temp: ListNode? = nil + while cur != nil { + temp = cur?.next + cur?.next = pre + pre = cur + cur = temp + } + return pre +} + +/// 递归 +/// - Parameter head: 头结点 +/// - Returns: 翻转后的链表头结点 +func reverseList2(_ head: ListNode?) -> ListNode? { + return reverse(pre: nil, cur: head) +} +func reverse(pre: ListNode?, cur: ListNode?) -> ListNode? { + if cur == nil { + return pre + } + let temp: ListNode? = cur?.next + cur?.next = pre + return reverse(pre: cur, cur: temp) +} +``` + ----------------------- * 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw) * B站视频:[代码随想录](https://space.bilibili.com/525438321)