LeetCode 100

傷城~ 2023-10-01 11:06 20阅读 0赞

1:盛最多水的容器。

给你 n 个非负整数 a1,a2,…,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

4ca6eb0cf704b6b9e90d56b5e7dd2954.png

方案1:直接暴力破解,O(n*n),但是最后会有时间限制。

方案2:双指针法,首尾指针,左指针小于右指针的值,左指针向右移动,否则右指针向左移动。终止条件是left < right。

2:三数之和。

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。注意:答案中不可以包含重复的三元组。

先排序数组,然后再利用双指针法(num[i] + num[L] + num[R],L初始化为i+1,R初始化为n-1)。对于已经排序完了数字,那么在固定了最小数字之后,只需要管最小数字之后的两个数是否能符合条件即可。

关键点在于不能重复,1:遇到重复数字,直接跳过,当前数字等于上一个数字时。

2:不满足匹配,则相应的向前向后移动。

3:遇到满足的匹配之后,还需要继续移动L和R,L和R在往前和往后的移动过程中如果遇到相同数字,那么也需要跳过。

  1. class Solution(object):
  2. def threeSum(self, nums):
  3. """
  4. :type nums: List[int]
  5. :rtype: List[List[int]]
  6. """
  7. sort_array = sorted(nums)
  8. res = []
  9. for i in range(len(sort_array)-2):
  10. if i>0 and sort_array[i] == sort_array[i-1]:
  11. continue
  12. if sort_array[i] > 0:
  13. break
  14. left = i + 1
  15. right = len(sort_array) - 1
  16. while(left < right):
  17. if sort_array[i] + sort_array[left] + sort_array[right] == 0:
  18. res.append([sort_array[i], sort_array[left], sort_array[right]])
  19. while(left < right and sort_array[left] == sort_array[left+1]):
  20. left += 1
  21. while(left < right and sort_array[right] == sort_array[right-1]):
  22. right -= 1
  23. left += 1
  24. right -= 1
  25. elif sort_array[i] + sort_array[left] + sort_array[right] < 0:
  26. left += 1
  27. else:
  28. right -= 1
  29. return res

3:删除链表的倒数第K个节点

类似于找到倒数第K个节点,要注意在先走K步的过程中是否为空。找到之后,要先置一个pre节点为None,在循环中用以保存第k个节点的上一个节点。

最后一个特殊情况就是,如果要删除的是第一个节点,那么这个pre节点为None,直接返回head.next即可。否则需要置pre.next = cur.next,之后再返回head。

  1. # Definition for singly-linked list.
  2. # class ListNode(object):
  3. # def __init__(self, val=0, next=None):
  4. # self.val = val
  5. # self.next = next
  6. class Solution(object):
  7. def removeNthFromEnd(self, head, n):
  8. """
  9. :type head: ListNode
  10. :type n: int
  11. :rtype: ListNode
  12. """
  13. if head is None:
  14. return head
  15. node = head
  16. for i in range(n):
  17. if node is None:
  18. return None
  19. else:
  20. node = node.next
  21. node_k = head
  22. node_k_pre = None
  23. while(node is not None):
  24. node = node.next
  25. node_k_pre = node_k
  26. node_k = node_k.next
  27. if node_k_pre is None:
  28. return head.next
  29. else:
  30. node_k_pre.next = node_k.next
  31. return head

4:合并两个有序链表:同剑指OFFER

5:电话号码全排列

回溯算法:

满足回溯?从一组中选定一个数字后,再从另一组中选数字,满足递归条件

终止条件?选择的次数等于输入字符串的长度

中间状态?每一轮选择的数字的列表。直接传入 path 也可。

  1. class Solution(object):
  2. def __init__(self):
  3. self.digit_info = {"2":['a','b','c'],
  4. "3":['d','e','f'],
  5. "4":['g','h','i'],
  6. "5":['j','k','l'],
  7. "6":['m','n','o'],
  8. "7":['p','q','r','s'],
  9. "8":['t','u','v'],
  10. "9":['w','x','y','z']}
  11. self.res_array = []
  12. def letterCombinations(self, digits):
  13. """
  14. :type digits: str
  15. :rtype: List[str]
  16. """
  17. if digits == '':
  18. return []
  19. #额外数组用来保存当前的排列
  20. char_array = []
  21. self.perm(char_array, digits)
  22. return self.res_array
  23. def perm(self, char_array, digits):
  24. if len(digits) == 0:
  25. self.res_array.append(''.join(char_array))
  26. return
  27. #不用考虑那么多,每次处理第一个字符就行了
  28. for x in self.digit_info[digits[0]]:
  29. char_array.append(x)
  30. self.perm(char_array, digits[1:])
  31. char_array.pop()

6:最长不重复子串

理解最关键,在做剑指offer的时候就想到了hash + 动态规划的方法,结果给记错了,还是要好好分析。

字符上一个出现位置记为-1,如果出现在hash中则记为hash中出现的最新位置,两个位置相减,如果大于上一个字符的最长不重复长度,那么只能为dp[i-1]+1, 否则取 i- j,这并不是可以简单的用min函数表达的,而是需要仔细分析,dvdf/abba。

  1. class Solution(object):
  2. def lengthOfLongestSubstring(self, s):
  3. """
  4. :type s: str
  5. :rtype: int
  6. """
  7. if len(s) == 0:
  8. return 0
  9. char_info = {}
  10. res = 0
  11. temp = 0
  12. for i in range(len(s)):
  13. j = -1
  14. if s[i] in char_info:
  15. j = char_info[s[i]]
  16. if i - j > temp:
  17. temp = temp + 1
  18. else:
  19. temp = i - j
  20. char_info[s[i]] = i
  21. res = max(res, temp)
  22. return res

滑动窗口方法:初始化一个滑动窗口,遍历数组,如果新元素在滑动窗口中有值,那么滑动窗口的左边界一直往前移动,直到新元素在滑动窗口中是新的值,再将新元素放入滑动窗口。此时这个窗口就代表以当前字符结尾的最长不重复子串长度。

3. 无重复字符的最长子串

30. 串联所有单词的子串

76. 最小覆盖子串

159. 至多包含两个不同字符的最长子串

209. 长度最小的子数组

239. 滑动窗口最大值

567. 字符串的排列

632. 最小区间

727. 最小窗口子序列

  1. class Solution(object):
  2. def lengthOfLongestSubstring(self, s):
  3. """
  4. :type s: str
  5. :rtype: int
  6. """
  7. if len(s) == 0:
  8. return 0
  9. window = []
  10. left = 0
  11. res = 0
  12. for right in range(len(s)):
  13. while(s[right] in window):
  14. window.remove(s[left])
  15. left += 1
  16. window.append(s[right])
  17. res = max(res, len(window))
  18. return res

7:括号匹配

使用栈来模拟括号的匹配,只入栈括号左半边,遇到括号右半边,弹出尾部元素,看是否匹配。

易错点:最后要判断栈长度,且遇到括号右半边的时候栈长度如果等于0,那么都是错误的匹配项。

  1. class Solution(object):
  2. def isValid(self, s):
  3. """
  4. :type s: str
  5. :rtype: bool
  6. """
  7. stack = []
  8. pair_info = {")":"(", "}":"{", "]":"["}
  9. for i in range(len(s)):
  10. if s[i] in ["(","[","{"]:
  11. stack.append(s[i])
  12. elif s[i] in ["}",")","]"]:
  13. if len(stack) == 0:
  14. return False
  15. if pair_info[s[i]] != stack.pop():
  16. return False
  17. if len(stack) != 0:
  18. return False
  19. return True

8:合并K个链表

方案1:额外数组+自定义排序方法

方案2:分支归并排序,再合并

方案3:python 自带最小堆 headq

  1. # Definition for singly-linked list.
  2. # class ListNode(object):
  3. # def __init__(self, val=0, next=None):
  4. # self.val = val
  5. # self.next = next
  6. class Solution(object):
  7. def mergeKLists(self, lists):
  8. """
  9. :type lists: List[ListNode]
  10. :rtype: ListNode
  11. """
  12. nodes = []
  13. for head in lists:
  14. while(head is not None):
  15. nodes.append(head)
  16. head = head.next
  17. def comp(node1, node2):
  18. if node1.val > node2.val:
  19. return 1
  20. elif node1.val < node2.val:
  21. return -1
  22. else:
  23. return 0
  24. sorted_nodes = sorted(nodes, comp)
  25. for i in range(len(sorted_nodes) - 1):
  26. sorted_nodes[i].next = sorted_nodes[i+1]
  27. if len(sorted_nodes) > 0:
  28. sorted_nodes[len(sorted_nodes)-1].next = None
  29. return sorted_nodes[0]
  30. else:
  31. return None

9:在排序数组中查找元素的第一个和最后一个位置

二分法进阶,如何找到一个元素最左和最右的位置?

知识点1:整数的除法,一定会舍弃最后的小数,在python中,int(3.6) = 3

知识点2:因此二分法中,如果mid = (left + right) / 2 取的是接近left的那个中间值

如果想取接近right的中间值,那么mid = (left + right + 1) / 2

知识点3:取到 mid 之后,如果 a[mid] 小于target,那么left = mid + 1,如果mid 大于target 那么right = mid - 1,如果a[mid] == target,就要看情况了,如果想取最左等于target的,那么right = mid。如果想取最右等于target的,那么 left = mid

  1. def find_right(nums, target):
  2. left = 0
  3. right = len(nums) - 1
  4. while(left < right):
  5. mid = (left + right + 1) / 2
  6. if nums[mid] > target:
  7. right = mid - 1
  8. elif nums[mid] == target:
  9. left = mid
  10. else:
  11. left = mid + 1
  12. return right
  13. def find_left(nums, target):
  14. left = 0
  15. right = len(nums) - 1
  16. while(left < right):
  17. mid = (left + right) / 2
  18. if nums[mid] < target:
  19. left = mid + 1
  20. elif nums[mid] == target:
  21. right = mid
  22. else:
  23. right = mid - 1
  24. return left

10:接雨水

单调栈的最佳实践

11:最大子数组和

最简单的动态规划dp[i] = max(dp[i-1] + num[i], num[i]),与剑指offer一致

12:两数相加(两个链表相加)

用到了之前学到的东西:1、初始化一个节点,复制一个节点,一个用于遍历,一个用于返回。2、不需要用数组存储,直接一个add_num保存上一位到这位的进位即可。3、注意边界条件,l1 或 l2 单独比较长的话那还要继续遍历处理,类似于合并有序链表。4、最后的最后,如果进位数add_num不等于0,那么还要多加一个node表示进位。(999 + 999,最后是四位数)

  1. # Definition for singly-linked list.
  2. # class ListNode(object):
  3. # def __init__(self, val=0, next=None):
  4. # self.val = val
  5. # self.next = next
  6. class Solution(object):
  7. def addTwoNumbers(self, l1, l2):
  8. """
  9. :type l1: ListNode
  10. :type l2: ListNode
  11. :rtype: ListNode
  12. """
  13. node = ListNode()
  14. node_temp = node
  15. add_num = 0
  16. while(l1 and l2):
  17. temp_num = l1.val + l2.val + add_num
  18. add_num = temp_num / 10
  19. node_temp.next = ListNode(temp_num % 10)
  20. node_temp = node_temp.next
  21. l1 = l1.next
  22. l2 = l2.next
  23. while(l1):
  24. temp_num = l1.val + add_num
  25. add_num = temp_num / 10
  26. node_temp.next = ListNode(temp_num % 10)
  27. node_temp = node_temp.next
  28. l1 = l1.next
  29. while(l2):
  30. temp_num = l2.val + add_num
  31. add_num = temp_num / 10
  32. node_temp.next = ListNode(temp_num % 10)
  33. node_temp = node_temp.next
  34. l2 = l2.next
  35. if add_num != 0:
  36. node_temp.next = ListNode(add_num)
  37. return node.next

13:两数之和

两数之和问题,一开始想的是先排序,然后双指针法,结果是想多了,人家要返回的是两个数字在原数组中的index,那么这个破坏原有index的方法是用不了了。

可以用额外空间法,利用一个hashmap,保存每个数字出现的位置,key为数组值,value为数组的index,在每一轮找完之后,再将当前数字放入到hashmap中,这样可以防止 [3,3] = 6 这种找到自己的情况。

暴力破解的话就是类似冒泡排序,双遍历即可。

  1. class Solution(object):
  2. def twoSum(self, nums, target):
  3. """
  4. :type nums: List[int]
  5. :type target: int
  6. :rtype: List[int]
  7. """
  8. num_map = {}
  9. for i in range(len(nums)):
  10. if num_map.get(target - nums[i]) is not None:
  11. return [i, num_map.get(target - nums[i])]
  12. num_map[nums[i]] = i

14:寻找两个正序数组的中位数

中位数定义:奇数就是中间的数, 偶数的时候是中间两个数字相加的平均,相当于一个归并排序

O(log(m+n)) 解法

【第 k 小数解法】你懂了吗? - 寻找两个正序数组的中位数 - 力扣(LeetCode) (leetcode-cn.com)

  1. class Solution(object):
  2. def findMedianSortedArrays(self, nums1, nums2):
  3. """
  4. :type nums1: List[int]
  5. :type nums2: List[int]
  6. :rtype: float
  7. """
  8. i = 0
  9. j = 0
  10. res_array = []
  11. while(i < len(nums1) and j < len(nums2)):
  12. if nums1[i] <= nums2[j]:
  13. res_array.append(nums1[i])
  14. i += 1
  15. else:
  16. res_array.append(nums2[j])
  17. j += 1
  18. while i < len(nums1):
  19. res_array.append(nums1[i])
  20. i += 1
  21. while j < len(nums2):
  22. res_array.append(nums2[j])
  23. j += 1
  24. if len(res_array) % 2 != 0:
  25. return res_array[len(res_array)/2]
  26. else:
  27. return float(res_array[len(res_array)/2] + res_array[len(res_array)/2 - 1]) / 2

高效解法:

  1. class Solution(object):
  2. def findMedianSortedArrays(self, nums1, nums2):
  3. """
  4. :type nums1: List[int]
  5. :type nums2: List[int]
  6. :rtype: float
  7. """
  8. def getKminelement(k):
  9. index1 = 0
  10. index2 = 0
  11. #k表示第k小的数字
  12. while True:
  13. #若一个数组走完,另外一个数组走完剩下的步即可
  14. if index1 == len(nums1):
  15. return nums2[index2 + k - 1]
  16. if index2 == len(nums2):
  17. return nums1[index1 + k - 1]
  18. #若k等于1,直接取二者最小
  19. if k == 1:
  20. return min(nums1[index1], nums2[index2])
  21. #表示往前走k/2步,两个数组求第k小,分别走k/2步,但不能超过数组长度
  22. new_index1 = min(len(nums1)-1, index1+k/2-1)
  23. new_index2 = min(len(nums2)-1, index2+k/2-1)
  24. if nums1[new_index1] < nums2[new_index2]:
  25. #由于index可能会更新为当前数组的最后一个数字,所以k更新为 k -= 跳过的步数
  26. k -= new_index1 - index1 + 1
  27. index1 = new_index1 + 1
  28. else:
  29. k -= new_index2 - index2 + 1
  30. index2 = new_index2 + 1
  31. if (len(nums1) + len(nums2)) % 2 == 1:
  32. return getKminelement((len(nums1) + len(nums2)+1)/2)
  33. else:
  34. return float(getKminelement(((len(nums1) + len(nums2))/2)) + \
  35. getKminelement((len(nums1) + len(nums2))/2 + 1)) / 2

15:每日温度

利用单调递减栈,找到下一个最大值,当前 index - 栈中弹出的元素的 index 就是相差的天数。

  1. class Solution(object):
  2. def dailyTemperatures(self, temperatures):
  3. """
  4. :type temperatures: List[int]
  5. :rtype: List[int]
  6. """
  7. stack = []
  8. res = [0 for i in temperatures]
  9. for i in range(len(temperatures)):
  10. while stack and temperatures[i] > temperatures[stack[-1]]:
  11. temp = stack.pop()
  12. res[temp] = i - temp
  13. stack.append(i)
  14. return res

16:滑动窗口最大值

方案1:构造滑动窗口。

方案2:构造单调栈。

其实也是单调栈的思路,但是有一点不一样的是,此题使用单调栈会超时,使用单调队列就可以。

猜想是因为用 stack 来 pop(0) 这个方法比较耗时间?

单调栈:

  1. class Solution(object):
  2. def maxSlidingWindow(self, nums, k):
  3. """
  4. :type nums: List[int]
  5. :type k: int
  6. :rtype: List[int]
  7. """
  8. stack = []
  9. res = []
  10. for i in range(len(nums)):
  11. for element in stack:
  12. if element <= i - k:
  13. stack.pop(0)
  14. while stack and nums[i] > nums[stack[-1]]:
  15. stack.pop()
  16. stack.append(i)
  17. if i >= k - 1:
  18. res.append(nums[stack[0]])
  19. return res

单调队列:collections.deque() / pop() / append() / popleft()

  1. class Solution(object):
  2. def maxSlidingWindow(self, nums, k):
  3. """
  4. :type nums: List[int]
  5. :type k: int
  6. :rtype: List[int]
  7. """
  8. window = collections.deque()
  9. res = []
  10. for i in range(len(nums)):
  11. while window and nums[i] > nums[window[-1]]:
  12. window.pop()
  13. window.append(i)
  14. while window[0] <= i - k:
  15. window.popleft()
  16. if i >= k - 1:
  17. res.append(nums[window[0]])
  18. return res

17 下一个排列

从后往前找,找到第一个相邻 i,j 满足 a[i] < a[j],[j, end)必然是降序序列

在[j , end)中从后往前找到第一个大于a[i] 的a[k],交换 a[i] a[k], [j, end)依然是降序序列

再将[j, end)转为升序排列,逆序一下即可。

比较奇怪的是,leetcode上的 Python 竟然不支持 切片方法的逆序[::-1] ,所以用了 list 的 reverse()方法。

  1. class Solution(object):
  2. def nextPermutation(self, nums):
  3. """
  4. :type nums: List[int]
  5. :rtype: None Do not return anything, modify nums in-place instead.
  6. """
  7. i = -1
  8. j = -1
  9. size = len(nums) - 1
  10. while(size > 0):
  11. if nums[size - 1] < nums[size]:
  12. i = size - 1
  13. j = size
  14. break
  15. size -= 1
  16. if i == -1:
  17. return nums.reverse()
  18. size = len(nums) - 1
  19. while(size >= j):
  20. if nums[size] > nums[i]:
  21. nums[i], nums[size] = nums[size], nums[i]
  22. break
  23. size -= 1
  24. size = len(nums) - 1
  25. while(j < size):
  26. nums[j], nums[size] = nums[size], nums[j]
  27. j += 1
  28. size -= 1
  29. return nums

18 括号生成

这里也用到了一个栈来保存括号,右括号的个数大于左括号的个数,则不满足条件。

经典的回溯法:四问?

1:是否满足回溯法这种结构?选定一个括号之后,要在‘(’ 和 ‘)’中再选一个,以此类推,满足递归结构

2:终止条件是什么?单个‘(’ 和 ‘)’ 的个数要同时等于 n,且不能大于 n,同时满足括号匹配原则。

3:是否需要visited 数组和 begin 变量?

4:状态变量是什么?结果是什么?状态变量 path 数组,保存当前 ‘(’ 和 ‘)’ 符号,结果是 res,保存满足条件的状态变量的合集。

  1. class Solution(object):
  2. def generateParenthesis(self, n):
  3. """
  4. :type n: int
  5. :rtype: List[str]
  6. """
  7. res = []
  8. def dfs(path, left, right):
  9. if left == n and right == n:
  10. res.append(''.join(path))
  11. return
  12. if left > n or right > n:
  13. return
  14. if path.count(')') > path.count('('):
  15. return
  16. if left < n:
  17. dfs(path + ['('], left + 1, right)
  18. if right < n:
  19. dfs(path + [')'], left, right + 1)
  20. path = []
  21. dfs(path, 0, 0)
  22. return res

19:最长有效括号

核心思想依然是用栈来找出匹配的括号的下标

括号匹配问题,依然利用栈来表达,栈中保存的是所有左括号的下标,遇到右括号则和左括号下标一起弹出到 res结果中,最后再对 res进行排序,排完序之后找到数据相连的最长长度即可。

  1. class Solution(object):
  2. def longestValidParentheses(self, s):
  3. """
  4. :type s: str
  5. :rtype: int
  6. """
  7. if s == '':
  8. return 0
  9. stack = []
  10. res = []
  11. for i in range(len(s)):
  12. if s[i] == ')':
  13. if len(stack) > 0:
  14. res.append(stack.pop())
  15. res.append(i)
  16. else:
  17. stack.append(i)
  18. left = 0
  19. right = 0
  20. max_length = 0
  21. res = sorted(res)
  22. for i in range(len(res)-1):
  23. if res[i] == res[i+1] - 1:
  24. right = i + 1
  25. max_length = max(max_length, right - left + 1)
  26. else:
  27. max_length = max(max_length, right - left + 1)
  28. left = i + 1
  29. right = i + 1
  30. return max_length

20:搜索旋转排序数组

核心思想:二分法,难点:先保证某一段区间是单调区间,判断这个 target 是否在这个区间内。

旋转数组的特性,当nums[mid] >= left (left, mid) 是递增,否则(mid, right)是递增

  1. class Solution(object):
  2. def search(self, nums, target):
  3. """
  4. :type nums: List[int]
  5. :type target: int
  6. :rtype: int
  7. """
  8. left = 0
  9. right = len(nums) - 1
  10. while(left <= right):
  11. mid = (left +right) / 2
  12. if nums[mid] == target:
  13. return mid
  14. #(left, mid)是递增
  15. if nums[mid] >= nums[left]:
  16. if target <= nums[mid] and target >= nums[left]:
  17. right = mid - 1
  18. else:
  19. left = mid + 1
  20. #(mid, right)是递增
  21. else:
  22. if target >= nums[mid] and target <= nums[right]:
  23. left = mid + 1
  24. else:
  25. right = mid - 1
  26. return -1

21:全排列

回溯算法:

满足回溯?数组元素每一位与它后面的元素交换,满足递归的条件

终止条件?交换当位的 index 等于数组长度

中间状态?使用数组本身作为状态,要用 num[:] 将其深拷贝过去。交换完一次之后还需要复位。

  1. class Solution(object):
  2. def permute(self, nums):
  3. """
  4. :type nums: List[int]
  5. :rtype: List[List[int]]
  6. """
  7. if len(nums) == 0:
  8. return 0
  9. res = []
  10. def dfs(index):
  11. if index == len(nums):
  12. res.append(nums[:])
  13. for i in range(index, len(nums)):
  14. nums[i], nums[index] = nums[index], nums[i]
  15. dfs(index + 1)
  16. nums[i], nums[index] = nums[index], nums[i]
  17. dfs(0)
  18. return res

22:子集

回溯算法:

满足回溯?数组中选定一个元素之后,在剩余元素中(其实是当前元素的后面的元素,因为要避免重复),可以选,也可以不选。满足递归的条件

终止条件?数组选到最后一个数字。index 元素等于数组长度-1

中间状态?使用path 数组作为状态,保存每一轮选择的数字。

  1. class Solution(object):
  2. def subsets(self, nums):
  3. """
  4. :type nums: List[int]
  5. :rtype: List[List[int]]
  6. """
  7. if len(nums) == 0:
  8. return []
  9. res = []
  10. def dfs(path, index):
  11. res.append(path)
  12. for i in range(index, len(nums)):
  13. dfs(path + [nums[i]], i + 1)
  14. dfs([], 0)
  15. return res

23:旋转图像

旋转矩阵 N

方案1:如果有额外数组,可以找出规律:

第 i 行,第 j 个元素,旋转90度后,处于第 N - i - 1列的 第 j 行 : a[i][j] = a[j][n-i-1]

  1. class Solution(object):
  2. def rotate(self, matrix):
  3. """
  4. :type matrix: List[List[int]]
  5. :rtype: None Do not return anything, modify matrix in-place instead.
  6. """
  7. if len(matrix) == 0:
  8. return matrix
  9. n = len(matrix)
  10. help_matrix = [[0 for i in range(len(matrix[0]))] for j in range(len(matrix))]
  11. for i in range(len(matrix)):
  12. for j in range(len(matrix[0])):
  13. help_matrix[j][n-i-1] = matrix[i][j]
  14. #leetcode 会强制检查输入 matrix,因此必须还有一层深拷贝
  15. matrix[:] = help_matrix
  16. return matrix

方案2:如果要原地旋转,那么旋转会导致四个相应的元素相互递归替换:

因此在遍历的时候也只需要处理1/4个矩阵 i< n/2 and j < n+1/2

记不住对应关系的话,直接记住 matrix[i][j] ,然后哪个元素 p旋转后可以到 i,j ? 下一个元素就是这个旋转的元素p,然后在找到可以旋转到 p 的 q元素。

matrix[i][j], matrix[n - j - 1][i], matrix[n - i - 1][n - j - 1], matrix[j][n - i - 1] \
= matrix[n - j - 1][i], matrix[n - i - 1][n - j - 1], matrix[j][n - i - 1], matrix[i][j]

哪一个元素经过旋转会到当前的 i,j 位置呢?

通过方案1的公式即可得出matrix[n - j - 1][i] -> matrix[i][j]

  1. class Solution(object):
  2. def rotate(self, matrix):
  3. """
  4. :type matrix: List[List[int]]
  5. :rtype: None Do not return anything, modify matrix in-place instead.
  6. """
  7. if len(matrix) == 0:

发表评论

表情:
评论列表 (有 0 条评论,20人围观)

还没有评论,来说两句吧...

相关阅读

    相关 LeetCode 100

    1:盛最多水的容器。 给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i

    相关 LeetCode》Hot 100

    持续更新中~~ No.461 汉明距离 题目描述:两个整数之间的汉明距离指的是这两个数字对应二进制位不同的位置的数目。给出两个整数 x 和 y,计算它们之间的汉明距离。

    相关 LeetCode 100

    问题描述: 给定两个二叉树,编写一个函数来检验它们是否相同。 如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。 示例 1: 输入:       1