小记:这道题昨天做了,没有什么思路,还是对双指针的理解太局限了,这里的双指针就是一个指向数组开头、一个指向数组结尾的指针,在通过加和的正负判断二者大小,最后用一个新数组储存值。
下面贴一下代码随想录给出的代码。
(版本一)双指针法
class Solution:
def sortedSquares(self, nums: List[int]) -> List[int]:
l, r, i = 0, len(nums)-1, len(nums)-1
res = [float('inf')] * len(nums) # 需要提前定义列表,存放结果
while l <= r:
if nums[l] ** 2 < nums[r] ** 2: # 左右边界进行对比,找出最大值
res[i] = nums[r] ** 2
r -= 1 # 右指针往左移动
else:
res[i] = nums[l] ** 2
l += 1 # 左指针往右移动
i -= 1 # 存放结果的指针需要往前平移一位
return res
(版本二)暴力排序法
class Solution:
def sortedSquares(self, nums: List[int]) -> List[int]:
for i in range(len(nums)):
nums[i] *= nums[i]
nums.sort()
return nums
(版本三)暴力排序法+列表推导法
class Solution:
def sortedSquares(self, nums: List[int]) -> List[int]:
return sorted(x*x for x in nums)
实现滑动窗口,主要确定如下三点:
窗口内是什么?
如何移动窗口的起始位置?
如何移动窗口的结束位置?
窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。
窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了(也就是该缩小了)。
窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
示例1:
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
示例2:
输入:target = 4, nums = [1,4,4]
输出:1
示例 3:
输入:target = 11, nums = [1,1,1,1,1,1,1,1]
输出:0
在没看任何解析的情况下思考,只能想到先排序后加和的办法,但这明显不是题目想要考察的。自己写的一个半部分代码(无法执行),没有体现出代码随想录中所教授“滑动窗口”的精髓。
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
start = 0
n = len(nums)
count = 0
for end in range(n):
count = count + nums[end]
if count >= target :
while count >= target:
count = count - nums[start]
start = start + 1
count = count + nums[start]
start = start - 1
(版本一)滑动窗口法
class Solution:
def minSubArrayLen(self, s: int, nums: List[int]) -> int:
l = len(nums)
left = 0
right = 0
min_len = float('inf')
cur_sum = 0 #当前的累加值
while right < l:
cur_sum += nums[right]
while cur_sum >= s: # 当前累加值大于目标值
min_len = min(min_len, right - left + 1)
cur_sum -= nums[left]
left += 1
right += 1
return min_len if min_len != float('inf') else 0
(版本二)暴力法
class Solution:
def minSubArrayLen(self, s: int, nums: List[int]) -> int:
l = len(nums)
min_len = float('inf')
for i in range(l):
cur_sum = 0
for j in range(i, l):
cur_sum += nums[j]
if cur_sum >= s:
min_len = min(min_len, j - i + 1)
break
return min_len if min_len != float('inf') else 0
简单看了视频后,自己写出的代码,也debug了好久,根据报错处理了很多特殊情况,比如返回0的情况,比如数组目前大于target,但是按照while内操作语句,减去第一个元素后,就小于target的情况。
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
start = 0
n = len(nums)
count = 0
result = n
resl = []
for end in range(n):
count = count + nums[end]
while count >= target:
subl = end - start + 1
if subl < result :
resl = nums[start:end+1]
result = min(subl,result)
if count - nums[start] >= target:
count = count - nums[start]
start = start + 1
else:
break
if result == n and count < target:
return 0
else:
return result
看了随想录的代码后,发现是我的上个版本给的result的初始值为n,会造成一些矛盾,才导致多了if判断,改正后如下。
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
start = 0
n = len(nums)
count = 0
result = 2*n
resl = []
for end in range(n):
count = count + nums[end]
while count >= target:
subl = end - start + 1
if subl < result :
resl = nums[start:end+1]
result = min(subl,result)
count = count - nums[start]
start = start + 1
if result == 2*n :
return 0
else :
return result
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
left, right, s, res = 0, -1, 0, float("inf")
for _ in range(len(nums)):
right += 1
s += nums[right]
while s >= target:
res = min(res, right - left + 1)
if res == 1:
return 1
s -= nums[left]
left += 1
return res if res != float("inf") else 0
你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果 种类 。
你想要尽可能多地收集水果。然而,农场的主人设定了一些严格的规矩,你必须按照要求采摘水果:
你只有 两个 篮子,并且每个篮子只能装 单一类型 的水果。每个篮子能够装的水果总量没有限制。
你可以选择任意一棵树开始采摘,你必须从 每棵 树(包括开始采摘的树)上 恰好摘一个水果 。采摘的水果应当符合篮子中的水果类型。每采摘一次,你将会向右移动到下一棵树,并继续采摘。
一旦你走到某棵树前,但水果不符合篮子的水果类型,那么就必须停止采摘。
给你一个整数数组 fruits ,返回你可以收集的水果的最大数目。
示例1:
输入:fruits = [1,2,1]
输出:3
解释:可以采摘全部 3 棵树。
示例2:
输入:fruits = [0,1,2,2]
输出:3
解释:可以采摘 [1,2,2] 这三棵树。
如果从第一棵树开始采摘,则只能采摘 [0,1] 这两棵树。
可以明确知道用滑动窗口方法,但是由于此题考虑变成了树的ID,而不是一个简单元素的求和sum,不知道如何对ID进行限制。
class Solution:
def totalFruit(self, fruits: List[int]) -> int:
start = 0
n = len(fruits)
count = 0
result = 0
resl = []
tree_id = []
for end in range(n):
if fruits[end] is not in tree_id:
count = count + 1
tree_id.append(fruits[end])
if count > 2:
while len(tree_id) > 2 :
start
subl = end - start + 1
if subl > result :
resl = fruits[start:end+1]
result = max(subl,result)
count = countfruits[start]
start = start + 1
class Solution:
def totalFruit(self, fruits: List[int]) -> int:
baskets = []
num = 0 # 连续的当前水果数量
name = -1 # 当前判断水果类别
maxFruits = 1
count = 0
for fruit in fruits:
if fruit in baskets:
if fruit == name:
num += 1
else:
name = fruit
num = 1
count += 1
else:
if len(baskets) != 2:
baskets.append(fruit)
name = fruit
num = 1
count += 1
else:
if maxFruits < count:
maxFruits = count
baskets = [name]
baskets.append(fruit)
name = fruit
count = num + 1
num = 1
return max(maxFruits, count)
滑动窗口,维护left和right,每次取两个数作为基准,right向右滑动 ··如果fruits[right]不是其中的就更新新的数为基准将left直接移动到right前面一格,然后再向前找left相等的最前面的定位left。 如果fruits[right]是其中的就更新ans
class Solution {
public:
int totalFruit(vector<int>& fruits) {
int left = 0,right = 0,ans = 0;
int ln = fruits[left],rn = fruits[right];
while(right < fruits.size()){
if(fruits[right] == rn || fruits[right] == ln){
ans = max(ans,right + 1 - left);
right++;
}else{
left = right - 1;
ln = fruits[left];
while(left >= 1 && fruits[left - 1] == ln) left--;
rn = fruits[right];
ans = max(ans,right + 1 - left);
}
}
return ans;
}
};
因为题目中给了只有2个篮子,所以没必要去维护一个元组来记录当前有哪些种类的水果,反而给自己增加难度,就用两个数去记录并判断就好了。
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 “” 。
注意:
对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
如果 s 中存在这样的子串,我们保证它是唯一的答案。
示例 1:
输入:s = “ADOBECODEBANC”, t = “ABC”
输出:“BANC”
解释:最小覆盖子串 “BANC” 包含来自字符串 t 的 ‘A’、‘B’ 和 ‘C’。
示例 2:
输入: s = “a”, t = “aa”
输出: “”
解释: t 中两个字符 ‘a’ 均应包含在 s 的子串中,
因此没有符合条件的子字符串,返回空字符串。
示例 3:
输入:s = “a”, t = “a”
输出:“a”
解释:整个字符串 s 是最小覆盖子串。
class Solution:
def minWindow(self, s: str, t: str) -> str:
start = 0
end = 0
n = len(s)
count = 2*n
lt = list(t)
for end in range(n):
if s[end] in lt:
lt.remove(s[end])
if lt == []:
if count < end-start+1:
count = end - start + 1
res = s[start,end+1]
思路:
采用类似滑动窗口的思路,即用两个指针表示窗口左端left和右端right。 向右移动right,保证left与right之间的字符串足够包含需要包含的所有字符, 而在保证字符串能够包含所有需要的字符条件下,向右移动left,保证left的位置对应为需要的字符,这样的 窗口才有可能最短,此时只需要判断当期窗口的长度是不是目前来说最短的,决定要不要更新minL和minR(这两个 变量用于记录可能的最短窗口的端点)
搞清楚指针移动的规则之后,我们需要解决几个问题,就是怎么确定当前窗口包含所有需要的字符,以及怎么确定left的 位置对应的是需要的字符。 这里我们用一个字典mem保存目标字符串t中所含字符及其对应的频数。比如t=“ABAc”,那么字典mem={“A”:2,“B”:1,“c”:1}, 只要我们在向右移动right的时候,碰到t中的一个字符,对应字典的计数就减一,那么当字典这些元素的值都不大于0的时候, 我们的窗口里面就包含了所有需要的字符;但判断字典这些元素的值都不大于0并不能在O(1)时间内实现,因此我们要用一个变量 来记录我们遍历过字符数目,记为t_len,当我们遍历s的时候,碰到字典中存在的字符且对应频数大于0,就说明我们还没有找到 足够的字符,那么就要继续向右移动right,此时t_len-=1;直到t_len变为0,就说明此时已经找到足够的字符保证窗口符合要求了。
所以接下来就是移动left。我们需要移动left,直到找到目标字符串中的字符,同时又希望窗口尽可能短,因此我们就希望找到的 left使得窗口的开头就是要求的字符串中的字符,同时整个窗口含有所有需要的字符数量。注意到,前面我们更新字典的时候, 比如字符"A",如果我们窗口里面有10个A,而目标字符串中有5个A,那此时字典中A对应的计数就是-5,那么我要收缩窗口又要保证 窗口能够包含所需的字符,那么我们就要在收缩窗口的时候增加对应字符在字典的计数,直到我们找到某个位置的字符A,此时字典中 的计数为0,就不可以再收缩了(如果此时继续移动left,那么之后的窗口就不可能含有A这个字符了),此时窗口为可能的最小窗口,比较 更新记录即可。
from collections import defaultdict
class Solution(object):
def minWindow(self, s, t):
"""
:type s: str
:type t: str
:rtype: str
"""
mem = defaultdict(int)
for char in t:
mem[char]+=1
t_len = len(t)
minLeft, minRight = 0,len(s)
left = 0
for right,char in enumerate(s):
if mem[char]>0:
t_len-=1
mem[char]-=1
if t_len==0:
while mem[s[left]]<0:
mem[s[left]]+=1
left+=1
if right-left<minRight-minLeft:
minLeft,minRight = left,right
mem[s[left]]+=1
t_len+=1
left+=1
return '' if minRight==len(s) else s[minLeft:minRight+1]
/**时间复杂度O(N),空间复杂度O(1); 技术:滑动窗口+计数索引(不知道是不是这样叫,可以理解为简单的Hash表实现)
这道题有一定难度,leetcode438 号题也可使用类似的思路,不过稍微简单一些。
1. 注意到题目的关键:"所有字母的最小子串",也就是说两个串都只能是字母。
2. 于是,可以开辟一个大小为64的数组,来存放数组中字母的频率(Frequency)。准确的说,
通过字母的ASCII码作为数组的索引,开辟空间的大小为26+6+26=58:26个大写字母,26个小写字母,
还有中间的6个非字母 A~Z[65~90] 非字母[91~96] a~z[97~122]
3. 滑动窗口的使用:分三种情况来移动窗口:(这里令当前窗口的左右边界分别为l,r,窗口的大小为winSize=r-l+1)
1) 当winSize < t.size() r++; 也就是窗口右边界向右移动
2) 当winSize == t.size() :
2.1) 当窗口中的字符已经符合要求了,直接返回return,已经找到了
2.2) 否则r++,窗口右边界向右移动
3) 当winSize > t.size()
3.1) 当窗口中的字符已经符合要求了,l++,窗口左边界向右移动
3.2) 否则r++,窗口右边界向右移动
4. 上面是滑动窗口的使用思路,具体实现上有一定的不同,下面是需要考虑到的要点:
1) 啥叫作窗口中的字符已经符合要求了?
2) 窗口滑动时的操作是关键
3) 要考虑到数组越界的问题
string minWindow(string s, string t) {
if (s.size() < t.size()) return "";
int sFreq[64] = { 0 }, tFreq[64] = { 0 }; // frequency数组
for (int i = 0; i < t.size(); i++) tFreq[t[i] - 'A']++;
int l = 0, r = -1, edge[2] = { -1, s.size() + 1 }; //edge数组表示要求的串的左右边界
while (l <= s.size() - t.size()) {
// < t.size() 直接窗口右边界右移,循环continue
if (r - l + 1 < t.size()) {
if (r + 1 < s.size()) { // 这里注意到数组越界
sFreq[s[++r] - 'A']++; continue;
}
else break;
}
// >= t.size() 先判断当前窗口中的字符是否满足“题目要求”
int i = 0;
while (i < 64) {
if (sFreq[i] < tFreq[i]) break;
i++;
}
if (i < 64) {
// 这里注意到数组越界
if (r + 1 < s.size()) sFreq[s[++r] - 'A']++;
else sFreq[s[l++] - 'A']--;
}
else {
if (r - l + 1 == t.size()) return string(s.begin() + l, s.begin() + r + 1);
else {
if (r - l < edge[1] - edge[0]) {
edge[0] = l;
edge[1] = r;
}
sFreq[s[l++] - 'A']--;
}
}
}
return edge[0] == -1 ? "" : string(s.begin() + edge[0], s.begin() + edge[1] + 1);
}
class Solution {
public String minWindow(String s, String t) {
/*
滑窗问题+数组统计
1.这道题和LC3.最长无重复子串长度 类似,不过这一题更难一点,因为要判断窗口内是否能凑得t
2.这种窗口内的元素能否凑成t的问题要关注数量,因此需要用HashMap或者数组来维护(A65 a97 z122)
3.我们不妨固定一个左边界,然后右边界一直向右扫描直至首个满足窗口的元素,此时必定是该左边界为起点最短长度
4.其他的长度必定比这个更长,因此变动左边界的情况下维护这个最短长度,并且要实时记录左右边界
时间复杂度:O(m+n) 空间复杂度:O(1)
*/
int lenS = s.length(), lenT = t.length();
if (lenS < lenT) return "";
int minL = 0, minR = -1;
int l = 0, r = -1;
int[] cntMap1 = new int[58], cntMap2 = new int[58];
// 统计t的数据
for (int i = 0; i < lenT; i++) {
cntMap1[t.charAt(i) - 'A']++;
}
// 统计窗口有效元素个数
int cnt = 0;
while (l < lenS) {
// 移动r指针直至满足条件
while (r < lenS && cnt < lenT) {
// 此时r指针加入窗口
++r;
// 当且仅当数目小于目标值才是有效数目
if (r < lenS && ++cntMap2[s.charAt(r) - 'A'] <= cntMap1[s.charAt(r) - 'A']) cnt++;
}
// 此时的窗口符合条件,若长度更小则可以更新
if (cnt == lenT && (minR == -1 || r - l < minR - minL)) {
minL = l;
minR = r;
}
// l指针每一轮都右移一位退出窗口
if (--cntMap2[s.charAt(l) - 'A'] < cntMap1[s.charAt(l) - 'A']) cnt--;
++l;
}
// s[minL,minR]就是答案
return s.substring(minL, minR + 1);
}
}
class Solution:
def minWindow(self, s: str, t: str) -> str:
need = collections.defaultdict(int)
for c in t:
need[c] += 1
need_count = len(t)
l = 0; res = (0, float('inf'))
for r,c in enumerate(s):
if need[c] > 0:
need_count -= 1
need[c] -= 1
if need_count == 0:
while True:
if need[s[l]] == 0:
break
need[s[l]] += 1
l += 1
if r-l < res[1]-res[0]:
res = (l,r)
need[s[l]] += 1
need_count += 1
l += 1
return '' if res[1]>len(s) else s[res[0]:res[1]+1]
小记:坚持循环不变量,每一条边都用左闭右开去遍历即可,最后判断,若n为奇数,单独填充中心元素。
你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
示例:
输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]
看了代码随想录的解答,坚持循环不变量,每一条边都用左闭右开去遍历即可,最后判断,若n为奇数,单独填充中心元素。
class Solution:
def generateMatrix(self, n: int) -> List[List[int]]:
nums = [[0] * n for _ in range(n)]
startx, starty = 0, 0 # 起始点
loop, mid = n // 2, n // 2 # 迭代次数、n为奇数时,矩阵的中心点
count = 1 # 计数
for offset in range(1, loop + 1) : # 每循环一层偏移量加1,偏移量从1开始
for i in range(starty, n - offset) : # 从左至右,左闭右开
nums[startx][i] = count
count += 1
for i in range(startx, n - offset) : # 从上至下
nums[i][n - offset] = count
count += 1
for i in range(n - offset, starty, -1) : # 从右至左
nums[n - offset][i] = count
count += 1
for i in range(n - offset, startx, -1) : # 从下至上
nums[i][starty] = count
count += 1
startx += 1 # 更新起始点
starty += 1
if n % 2 != 0 : # n为奇数时,填充中心点
nums[mid][mid] = count
return nums
class Solution:
def generateMatrix(self, n: int) -> List[List[int]]:
# matrix = [[0]*n for _ in range(n)]
# dirs = [(0,1),(1,0),(0,-1),(-1,0)]
# row,col,idx = 0,0,0
# for num in range(1,n**2+1):
# matrix[row][col] = num
# dx,dy = dirs[idx]
# r,c = row+dx,col+dy
# if r<0 or r>=n or c<0 or c>=n or matrix[r][c]>0:
# idx = (idx+1) %4
# dx,dy = dirs[idx]
# row,col = row+dx,col+dy
# return matrix
#模拟法二
matrix = [[0]*n for _ in range(n)]
top,bottom,left,right = 0,n-1,0,n-1
num = 1
while top<=bottom and left<=right:
for col in range(left,right+1):
matrix[top][col] = num
num+=1
for row in range(top+1,bottom+1):
matrix[row][right]= num
num+=1
if left<right and top<bottom:
for tp in range(right-1,left,-1):
matrix[bottom][tp] = num
num+=1
for bt in range(bottom,top,-1):
matrix[bt][left] = num
num+=1
top+=1
bottom-=1
left+=1
right-=1
return matrix
给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。
示例1:
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]
class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
m = len(matrix)
n = len(matrix[0])
if m == 1:
return matrix[0]
elif n == 1:
return [matrix[i][0] for i in range(m)]
nums = []
startx, starty = 0, 0
loop = min(m,n)//2 # 起始点
for offset in range(1, loop + 1) : # 每循环一层偏移量加1,偏移量从1开始
for i in range(starty, n - offset) : # 从左至右,左闭右开
nums.append(matrix[startx][i])
for i in range(startx, m - offset) : # 从上至下
nums.append(matrix[i][n - offset])
for i in range(n - offset, starty, -1) : # 从右至左
nums.append(matrix[m - offset][i])
for i in range(m - offset, startx, -1) : # 从下至上
nums.append(matrix[i][starty])
startx += 1 # 更新起始点
starty += 1
if m > n :
if n % 2 != 0:
first = n // 2
end = m - 2 * first
for j in range(first,end+first):
nums.append(matrix[j][first])
elif m < n :
if m % 2 != 0:
first = m // 2
end = n - 2 * first
for j in range(first,end+first):
nums.append(matrix[first][j])
else :
mid = n // 2
if n % 2 != 0 : # n为奇数时,填充中心点
nums.append(matrix[mid][mid])
return nums
小记:没看任何参考自己写出来的,根据无数次debug添加了很多判断条件,简介代码还需学习。
class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
rowlen = len(matrix)
columnlen = len(matrix[0])
cl = 0
rt = 0
total = rowlen*columnlen
i = 0
t = "right"
x = 0
y = 0
out = []
while i < total:
if t == "right":
x = rt
for u in range(cl,columnlen):
out.append(matrix[x][u])
i += 1
rt += 1
t = "down"
elif t == "down":
y = columnlen - 1
for u in range(rt, rowlen):
out.append(matrix[u][y])
i += 1
columnlen -= 1
t = "left"
elif t == "left":
x = rowlen -1
for u in range(columnlen -1, cl -1, -1):
out.append(matrix[x][u])
i += 1
rowlen -= 1
t = "up"
elif t == "up":
y = cl
for u in range(rowlen -1, rt -1, -1):
out.append(matrix[u][y])
i += 1
cl += 1
t = "right"
return out
class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
m = len(matrix)
n = len(matrix[0])
nums = []
startx, starty = 0, 0
count = 0
total = m*n
offset = 1
while count < total:
if starty == n - offset and startx == m - offset :
mid = n // 2
nums.append(matrix[mid][mid])
count = count + 1
break
elif starty == n - offset :
for i in range(startx, m - offset+1):
nums.append(matrix[i][n - offset])
count = count + 1
break
elif startx == m - offset :
for i in range(starty, n - offset+1) : # 从左至右,左闭右开
nums.append(matrix[startx][i])
count = count + 1
break
for i in range(starty, n - offset) : # 从左至右,左闭右开
nums.append(matrix[startx][i])
count = count + 1
for i in range(startx, m - offset) : # 从上至下
nums.append(matrix[i][n - offset])
count = count + 1
for i in range(n - offset, starty, -1) : # 从右至左
nums.append(matrix[m - offset][i])
count = count + 1
for i in range(m - offset, startx, -1) : # 从下至上
nums.append(matrix[i][starty])
count = count + 1
startx += 1 # 更新起始点
starty += 1
offset = offset + 1
return nums
看下来,还是力扣给出的代码简洁,但是处理逻辑上比代码随想录的坚持左闭右开要复杂一点。
对于这种螺旋遍历的方法,重要的是要确定上下左右四条边的位置,那么初始化的时候,上边up就是0,下边down就是m-1,左边left是0,右边right是n-1。然后我们进行while循环,先遍历上边,将所有元素加入结果res,然后上边下移一位,如果此时上边大于下边,说明此时已经遍历完成了,直接break。
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
if(matrix.empty() || matrix[0].empty()) return {};
vector<int> res;
int m = matrix.size(), n = matrix[0].size();
// 确定上下左右四条边的位置
int up = 0, down = m - 1, left = 0, right = n - 1;
while (true)
{
for (int i = left; i <= right; i++) res.push_back(matrix[up][i]);
if (++up > down) break;
for (int i = up; i <= down; i++) res.push_back(matrix[i][right]);
if (--right < left) break;
for (int i = right; i >= left; i--) res.push_back(matrix[down][i]);
if (--down < up) break;
for (int i = down; i >= up; i--) res.push_back(matrix[i][left]);
if (++left > right) break;
}
return res;
}
};
class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
m = len(matrix)
n = len(matrix[0])
nums = []
startx, starty = 0, 0
count = 0
total = m*n
offset = 1
while count < total:
if count == total - 1 and m == n and m % 2 != 0:
nums.append(matrix[startx][startx])
break
for i in range(starty, n - offset) : # 从左至右,左闭右开
nums.append(matrix[startx][i])
count = count + 1
if count == total - 1 :
nums.append(matrix[startx][i+1])
break
for i in range(startx, m - offset) : # 从上至下
nums.append(matrix[i][n - offset])
count = count + 1
if count == total - 1 :
nums.append(matrix[i+1][n - offset])
break
for i in range(n - offset, starty, -1) : # 从右至左
nums.append(matrix[m - offset][i])
count = count + 1
for i in range(m - offset, startx, -1) : # 从下至上
nums.append(matrix[i][starty])
count = count + 1
startx += 1 # 更新起始点
starty += 1
offset = offset + 1
return nums
部分内容参考自:力扣官网、代码随想录。