diff --git a/problems/0027.移除元素.md b/problems/0027.移除元素.md index fd24e8f8..e99fee91 100644 --- a/problems/0027.移除元素.md +++ b/problems/0027.移除元素.md @@ -183,28 +183,24 @@ class Solution { Python: -```python +```python3 class Solution: - """双指针法 - 时间复杂度:O(n) - 空间复杂度:O(1) - """ - - @classmethod - def removeElement(cls, nums: List[int], val: int) -> int: - fast = slow = 0 - - while fast < len(nums): - - if nums[fast] != val: - nums[slow] = nums[fast] - slow += 1 - - # 当 fast 指针遇到要删除的元素时停止赋值 - # slow 指针停止移动, fast 指针继续前进 - fast += 1 - - return slow + def removeElement(self, nums: List[int], val: int) -> int: + if nums is None or len(nums)==0: + return 0 + l=0 + r=len(nums)-1 + while l>, path: &mut Vec, nums: &Vec, used: &mut Vec) { + let len = nums.len(); + if path.len() == len { + result.push(path.clone()); + return; + } + for i in 0..len { + if used[i] == true { continue; } + used[i] = true; + path.push(nums[i]); + Self::backtracking(result, path, nums, used); + path.pop(); + used[i] = false; + } + } + + pub fn permute(nums: Vec) -> Vec> { + let mut result: Vec> = Vec::new(); + let mut path: Vec = Vec::new(); + let mut used = vec![false; nums.len()]; + Self::backtracking(&mut result, &mut path, &nums, &mut used); + result + } +} +``` + ### C ```c diff --git a/problems/0054.螺旋矩阵.md b/problems/0054.螺旋矩阵.md index 0d79fdf9..8f2691fe 100644 --- a/problems/0054.螺旋矩阵.md +++ b/problems/0054.螺旋矩阵.md @@ -171,6 +171,30 @@ class Solution: return res ``` - +```python3 +class Solution: + def spiralOrder(self, matrix: List[List[int]]) -> List[int]: + r=len(matrix) + if r == 0 or len(matrix[0])==0: + return [] + c=len(matrix[0]) + res=matrix[0] + + if r>1: + for i in range (1,r): + res.append(matrix[i][c-1]) + for j in range(c-2, -1, -1): + res.append(matrix[r-1][j]) + if c>1: + for i in range(r-2, 0, -1): + res.append(matrix[i][0]) + + M=[] + for k in range(1, r-1): + e=matrix[k][1:-1] + M.append(e) + + return res+self.spiralOrder(M) +``` -----------------------
diff --git a/problems/0134.加油站.md b/problems/0134.加油站.md index e6dec44b..e5d50a9b 100644 --- a/problems/0134.加油站.md +++ b/problems/0134.加油站.md @@ -471,5 +471,73 @@ int canCompleteCircuit(int* gas, int gasSize, int* cost, int costSize){ } ``` +### Scala + +暴力解法: + +```scala +object Solution { + def canCompleteCircuit(gas: Array[Int], cost: Array[Int]): Int = { + for (i <- cost.indices) { + var rest = gas(i) - cost(i) + var index = (i + 1) % cost.length // index为i的下一个节点 + while (rest > 0 && i != index) { + rest += (gas(index) - cost(index)) + index = (index + 1) % cost.length + } + if (rest >= 0 && index == i) return i + } + -1 + } +} +``` + +贪心算法,方法一: + +```scala +object Solution { + def canCompleteCircuit(gas: Array[Int], cost: Array[Int]): Int = { + var curSum = 0 + var min = Int.MaxValue + for (i <- gas.indices) { + var rest = gas(i) - cost(i) + curSum += rest + min = math.min(min, curSum) + } + if (curSum < 0) return -1 // 情况1: gas的总和小于cost的总和,不可能到达终点 + if (min >= 0) return 0 // 情况2: 最小值>=0,从0号出发可以直接到达 + // 情况3: min为负值,从后向前看,能把min填平的节点就是出发节点 + for (i <- gas.length - 1 to 0 by -1) { + var rest = gas(i) - cost(i) + min += rest + if (min >= 0) return i + } + -1 + } +} +``` + +贪心算法,方法二: + +```scala +object Solution { + def canCompleteCircuit(gas: Array[Int], cost: Array[Int]): Int = { + var curSum = 0 + var totalSum = 0 + var start = 0 + for (i <- gas.indices) { + curSum += (gas(i) - cost(i)) + totalSum += (gas(i) - cost(i)) + if (curSum < 0) { + start = i + 1 // 起始位置更新 + curSum = 0 // curSum从0开始 + } + } + if (totalSum < 0) return -1 // 说明怎么走不可能跑一圈 + start + } +} +``` + -----------------------
diff --git a/problems/0209.长度最小的子数组.md b/problems/0209.长度最小的子数组.md index c75df661..570242f9 100644 --- a/problems/0209.长度最小的子数组.md +++ b/problems/0209.长度最小的子数组.md @@ -179,8 +179,27 @@ class Solution: index += 1 return 0 if res==float("inf") else res ``` - - +```python3 +#滑动窗口 +class Solution: + def minSubArrayLen(self, target: int, nums: List[int]) -> int: + if nums is None or len(nums)==0: + return 0 + lenf=len(nums)+1 + total=0 + i=j=0 + while (j=target): + lenf=min(lenf,j-i) + total=total-nums[i] + i+=1 + if lenf==len(nums)+1: + return 0 + else: + return lenf +``` Go: ```go func minSubArrayLen(target int, nums []int) int { diff --git a/problems/0234.回文链表.md b/problems/0234.回文链表.md index eeee6fa5..0dbe88c4 100644 --- a/problems/0234.回文链表.md +++ b/problems/0234.回文链表.md @@ -218,59 +218,41 @@ class Solution { ```python #数组模拟 class Solution: - def isPalindrome(self, head: ListNode) -> bool: - length = 0 - tmp = head - while tmp: #求链表长度 - length += 1 - tmp = tmp.next - - result = [0] * length - tmp = head - index = 0 - while tmp: #链表元素加入数组 - result[index] = tmp.val - index += 1 - tmp = tmp.next - - i, j = 0, length - 1 - while i < j: # 判断回文 - if result[i] != result[j]: + def isPalindrome(self, head: Optional[ListNode]) -> bool: + list=[] + while head: + list.append(head.val) + head=head.next + l,r=0, len(list)-1 + while l<=r: + if list[l]!=list[r]: return False - i += 1 - j -= 1 - return True - + l+=1 + r-=1 + return True + #反转后半部分链表 class Solution: - def isPalindrome(self, head: ListNode) -> bool: - if head == None or head.next == None: - return True - slow, fast = head, head - while fast and fast.next: - pre = slow - slow = slow.next - fast = fast.next.next - - pre.next = None # 分割链表 - cur1 = head # 前半部分 - cur2 = self.reverseList(slow) # 反转后半部分,总链表长度如果是奇数,cur2比cur1多一个节点 - while cur1: - if cur1.val != cur2.val: - return False - cur1 = cur1.next - cur2 = cur2.next - return True + def isPalindrome(self, head: Optional[ListNode]) -> bool: + fast = slow = head - def reverseList(self, head: ListNode) -> ListNode: - cur = head - pre = None - while(cur!=None): - temp = cur.next # 保存一下cur的下一个节点 - cur.next = pre # 反转 - pre = cur - cur = temp - return pre + # find mid point which including (first) mid point into the first half linked list + while fast and fast.next: + fast = fast.next.next + slow = slow.next + node = None + + # reverse second half linked list + while slow: + slow.next, slow, node = node, slow.next, slow + + # compare reversed and original half; must maintain reversed linked list is shorter than 1st half + while node: + if node.val != head.val: + return False + node = node.next + head = head.next + return True ``` ### Go diff --git a/problems/0459.重复的子字符串.md b/problems/0459.重复的子字符串.md index 4f45f4d7..0c662148 100644 --- a/problems/0459.重复的子字符串.md +++ b/problems/0459.重复的子字符串.md @@ -49,7 +49,7 @@ 数组长度为:len。 -如果len % (len - (next[len - 1] + 1)) == 0 ,则说明 (数组长度-最长相等前后缀的长度) 正好可以被 数组的长度整除,说明有该字符串有重复的子字符串。 +如果len % (len - (next[len - 1] + 1)) == 0 ,则说明数组的长度正好可以被 (数组长度-最长相等前后缀的长度) 整除 ,说明该字符串有重复的子字符串。 **数组长度减去最长相同前后缀的长度相当于是第一个周期的长度,也就是一个周期的长度,如果这个周期可以被整除,就说明整个数组就是这个周期的循环。** @@ -63,7 +63,7 @@ next[len - 1] = 7,next[len - 1] + 1 = 8,8就是此时字符串asdfasdfasdf的最长相同前后缀的长度。 -(len - (next[len - 1] + 1)) 也就是: 12(字符串的长度) - 8(最长公共前后缀的长度) = 4, 4正好可以被 12(字符串的长度) 整除,所以说明有重复的子字符串(asdf)。 +(len - (next[len - 1] + 1)) 也就是: 12(字符串的长度) - 8(最长公共前后缀的长度) = 4, 12 正好可以被 4 整除,所以说明有重复的子字符串(asdf)。 C++代码如下:(这里使用了前缀表统一减一的实现方式) diff --git a/problems/0704.二分查找.md b/problems/0704.二分查找.md index 98b55505..eec97a78 100644 --- a/problems/0704.二分查找.md +++ b/problems/0704.二分查找.md @@ -220,19 +220,21 @@ class Solution: (版本二)左闭右开区间 -```python -class Solution: +```class Solution: def search(self, nums: List[int], target: int) -> int: - left,right =0, len(nums) - while left < right: - mid = (left + right) // 2 - if nums[mid] < target: - left = mid+1 - elif nums[mid] > target: - right = mid + if nums is None or len(nums)==0: + return -1 + l=0 + r=len(nums)-1 + while (l<=r): + m = round(l+(r-l)/2) + if nums[m] == target: + return m + elif nums[m] > target: + r=m-1 else: - return mid - return -1 + l=m+1 + return -1 ``` **Go:** diff --git a/problems/0925.长按键入.md b/problems/0925.长按键入.md index 58fe99b7..3924c181 100644 --- a/problems/0925.长按键入.md +++ b/problems/0925.长按键入.md @@ -129,29 +129,21 @@ class Solution { ``` ### Python ```python -class Solution: - def isLongPressedName(self, name: str, typed: str) -> bool: - i, j = 0, 0 - m, n = len(name) , len(typed) - while i< m and j < n: - if name[i] == typed[j]: # 相同时向后匹配 - i += 1 - j += 1 - else: # 不相同 - if j == 0: return False # 如果第一位不相同,直接返回false - # 判断边界为n-1,若为n会越界,例如name:"kikcxmvzi" typed:"kiikcxxmmvvzzz" - while j < n - 1 and typed[j] == typed[j-1]: j += 1 - if name[i] == typed[j]: - i += 1 - j += 1 - else: return False - # 说明name没有匹配完 - if i < m: return False - # 说明type没有匹配完 - while j < n: - if typed[j] == typed[j-1]: j += 1 - else: return False - return True + i = j = 0 + while(i List[int]: + res=[] + for num in nums: + res.append(num**2) + return sorted(res) +``` + 这个时间复杂度是 O(n + nlogn), 可以说是O(nlogn)的时间复杂度,但为了和下面双指针法算法时间复杂度有鲜明对比,我记为 O(n + nlog n)。 diff --git a/problems/1005.K次取反后最大化的数组和.md b/problems/1005.K次取反后最大化的数组和.md index 8e161594..8d721b9f 100644 --- a/problems/1005.K次取反后最大化的数组和.md +++ b/problems/1005.K次取反后最大化的数组和.md @@ -289,6 +289,28 @@ function largestSumAfterKNegations(nums: number[], k: number): number { }; ``` +### Scala + +```scala +object Solution { + def largestSumAfterKNegations(nums: Array[Int], k: Int): Int = { + var num = nums.sortWith(math.abs(_) > math.abs(_)) + + var kk = k // 因为k是不可变量,所以要赋值给一个可变量 + for (i <- num.indices) { + if (num(i) < 0 && kk > 0) { + num(i) *= -1 // 取反 + kk -= 1 + } + } + + // kk对2取余,结果为0则为偶数不需要取反,结果为1为奇数,只需要对最后的数字进行反转就可以 + if (kk % 2 == 1) num(num.size - 1) *= -1 + + num.sum // 最后返回数字的和 + } +} +``` diff --git a/problems/面试题02.07.链表相交.md b/problems/面试题02.07.链表相交.md index 6ea9a037..abf7a2f8 100644 --- a/problems/面试题02.07.链表相交.md +++ b/problems/面试题02.07.链表相交.md @@ -160,6 +160,8 @@ class Solution: 那么,只要其中一个链表走完了,就去走另一条链表的路。如果有交点,他们最终一定会在同一个 位置相遇 """ + if headA is None or headB is None: + return None cur_a, cur_b = headA, headB # 用两个指针代替a和b