前言
记录刷题过程。没有什么系统方法,全凭自己感觉。看了他人的题解。
有的会有python,由于不是很熟python,所以会写一些基础知识点。
一、1:两数之和(哈希,简单)
给定一个整数数组
nums和一个整数目标值target,请你在该数组中找出 和为目标值target的那 两个 整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。
你可以按任意顺序返回答案。
思路:使用哈希表map<值,下标>,每次都去map中寻找。若找不到,则加入到map中;若找到,则返回下标。
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> res;
map<int,int> mp;
for(int i=0;i<nums.size();i++){
if(mp.find(target-nums[i])!=mp.end()){
res={i,mp[target-nums[i]]};
return res;
}
else{
mp[nums[i]]=i;
}
}
return res;
}
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
dic = defaultdict(int)
for i in range(len(nums)):
if target - nums[i] in dic:
return [dic[target - nums[i]], i]
else:
dic[nums[i]] = i
暴力解法:直接二重循环,没有超时
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> res;
for(int i=0;i<nums.size();i++){
for(int j=i+1;j<nums.size();j++){
if(nums[i]+nums[j]==target){
res={i,j};
return res;
}
}
}
return res;
}
python:
class Solution(object):
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
res=[0]*2
for i,num in enumerate(nums):
if (target-num) in nums:
res[0]=i
res[1]=nums.index(target-num)
if res[0]!=res[1]:
break
else:
res=[0,0]
return res
由于nums.index的时间复杂度是O(n),所以总的时间复杂度仍是O(n2)
二、49:字母异位词分组(哈希,中等)
给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
字母异位词是通过重新排列不同单词或短语的字母而形成的单词或短语,并使用所有原字母一次
思路:相同的异位词排序后相同。因此进行遍历时要对每个string进行排序,排序后的结果作为key,原string作为value。然后将map中的每个value加入到二维vector中。
注:二维vector要注意分配空间:res.reserve(行数)
map遍历:for(auto it=mp.begin();it!=mp.end();it++)
vector<vector<string>> groupAnagrams(vector<string>& strs) {
vector<vector<string>> res;
string str;
map<string,vector<string>> mp;
for(int i=0;i<strs.size();i++){
str=strs[i];
sort(str.begin(),str.end());
mp[str].push_back(strs[i]);
}
res.reserve(mp.size());//预先分配空间
for(auto it=mp.begin();it!=mp.end();it++){
res.push_back(it->second);
}
return res;
}
def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
res = []
dic = {}
for tmp in strs:
x = "".join(
sorted(tmp)
) # 字符串排序后是一个个字母,要操作重新连为一个字符串
if x in dic:
dic[x].append(tmp)
else:
dic[x] = [tmp]
for val in dic.values():
res.append(val)
return res
题解:
class Solution:
def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
d = defaultdict(list) # 如果 key 不在字典中,则自动插入一个空列表
for s in strs:
sorted_s = ''.join(sorted(s)) # 把 s 排序,作为哈希表的 key
d[sorted_s].append(s) # 排序后相同的字符串分到同一组
return list(d.values()) # 哈希表的 value 保存分组后的结果
时间复杂度:O(nmlogm)
三、128:最长连续序列(哈希,中等)
给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
请你设计并实现时间复杂度为 O(n) 的算法解决此问题。
思路:题目要求实现时间复杂度为
O(n)的算法,看的题解使用set,先进行去重。然后遍历set集合,判断每一个数字是不是序列的开头,
如果是开头,即该数字的前一个数*it-1,不在集合中,此时序列长度为1,当前开头数字为temp;然后利用while循环判断一个数字的下一个数字是否在集合中,即判断temp+1;
若temp+1在集合中,序列长度++,temp++,继续判断;
若不在集合中,则循环终止;
while循环终止后,使用max函数记录最大序列长度。
如果不是开头,则将该数字跳过,判断下一个数字。
复杂度分析:(转自leetcode官方题解复杂度分析)
外层循环需要 O(n) 的时间复杂度,只有当一个数是连续序列的第一个数的情况下才会进入内层循环,然后在内层循环中匹配连续序列中的数,因此数组中的每个数只会进入内层循环一次。根据上述分析可知,总时间复杂度为 O(n)
注:set遍历:for(auto it=se.begin();it!=se.end();it++) cout<<*it;
int longestConsecutive(vector<int>& nums) {
set<int> se;
for(int i=0;i<nums.size();i++){
se.insert(nums[i]);//去重
}
int now=0,maxx=0;
for(auto it=se.begin();it!=se.end();it++){
int num=*it-1;
if(!se.count(num)){
now=1;
int temp=*it;
while(se.count(temp+1)){
now++;
temp++;
}
maxx=max(maxx,now);
}
}
return maxx;
}
注:使用sort排序,然后一层循环求最大长度也可以过,复杂度O(nlogn)时间复杂度是 O(n log n)
四、283:移动零(双指针,简单)
思路:用数组a来保存nums中不是0的下标,非零数一定前移或者不移动,所以直接遍历nums,进行覆盖即可,将剩余部分补0;
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int a[10005];
int k=0;
int len=nums.size();
for(int i=0;i<nums.size();i++){
if(nums[i]!=0) {
a[k]=i;
k++;
}
}
for(int i=0;i<k;i++){
nums[i]=nums[a[i]];
}
for(int i=k;i<len;i++){
nums[i]=0;
}
}
};
五、11:盛水最多的容器(双指针,中等)
思路:面积为底边长乘以两边界中短板的长度。指针i,j分别指向开头和结尾;每次把值小的那一个往中间移一位。因为向内移,底边必然减少1;若移长板,则水槽的短板 min(h[i],h[j]) 不变或变小,面积必然减小;若移短板,则水槽的短板 min(h[i],h[j]) 不变或变大,面积可能不变或变大。
int maxArea(vector<int>& height) {
int maxx=0,area;
int i=0,j=height.size()-1;
while(i<j){
area=min(height[i],height[j])*(j-i);
maxx=max(maxx,area);
if(height[i]<height[j]) i++;
else j--;
}
return maxx;
}
注:暴力解法,i,j指向开头,直接二重循环会超时 ,O(n2)
六、15:三数之和(双指针,中等)
思路:先排序从小到大;固定一个指针i,让指针j指向i的下一个,k指向结尾。由于不允许重复输出,所以当nums[i]==nums[i-1]时跳过,进行下一轮循环。当三者相加为0时,记录结果;大于0时,说明nums[k]大了,所以k--;小于0时,说明nums[j]小了,所以j++。同样也要进行重复数值的跳过。
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
int i=0,j,k;
sort(nums.begin(),nums.end());
vector<vector<int>> res;
vector<int> temp;
for(int i=0;i<nums.size()-2;i++){
if(i>0&&nums[i]==nums[i-1]) continue;
j=i+1;
k=nums.size()-1;
while(j<k){
if(nums[i]+nums[j]+nums[k]==0){
temp={nums[i],nums[j],nums[k]};
res.push_back(temp);
while(j+1<nums.size()&&nums[j]==nums[j+1]) j++;
while(k-1>0&&nums[k]==nums[k-1]) k--;
k--;
j++;
}
else if(nums[i]+nums[j]+nums[k]>0) k--;
else j++;
}
}
return res;
}
};
七:42:接雨水(双指针,困难)
思路:
数组 height 中的每个元素,向左和向右找到其左边和右边的最大高度lmax和rmax,然后每个下标i能接的雨水量为min(lmax,rmax)−height[i]
双指针。
指针l指向开头只会向左移动,r指向结尾只会向右移动;两个变量lmax为从左边开始的最大值,rmax为从右边开始的最大值。
当指针l<r时:注意不断更新lmax和rmax的值;
若height[l]<height[r],则l++,注意lmax是否更新,l处所接的雨水为lmax-height[l];
若height[l]≥height[r],则r++,注意rmax是否更新,r处所接的雨水为rmax-height[r];
int trap(vector<int>& height) {
int l=0,r=height.size()-1;
int lmax=height[l],rmax=height[r],res=0;
while(l<r){
if(height[l]<height[r]){
l++;
lmax=max(lmax,height[l]);
res+=lmax-height[l];
}
else{
r--;
rmax=max(rmax,height[r]);
res+=rmax-height[r];
}
}
return res;
}
八、3:无重复字符的最长字串(滑动窗口,中等)
思路:双指针i,j表示滑动窗口的长度,依次移动j。
若此时滑动窗口内有与下一个字符相等的字符,则移动i到重复字符的下一个位置。
注:C++find函数:int index=s.find(想要找到的字符或字符串,开始查找的位置)
if(index==string::npos) 没找到
int lengthOfLongestSubstring(string s) {
int len = s.size();
int i = 0, j = 0;
int res = 0;
if (len == 0 || len == 1)
return len;
while (j < len - 1) {
int index = s.find(s[j + 1], i);
if (index <= j) {
i = index + 1;
}
j++;
res = max(res, j - i + 1);
}
return res;
}
九、438:找到字符串中所有字母异位词(滑动窗口,中等)
思路:题目中说明只有小写字母,用两个向量,一个保存p中每个字母出现的次数,一个保存s中长度为lenp时每个字母出现的次数。使用滑动窗口来实现,在滑动中维护窗口中每种字母的数量,当窗口中每种字母的数量与字符串 p 中每种字母的数量相同时,则说明当前窗口为字符串 p 的异位词。
要注意s和p的长度,当p的长度大于s的长度时,无解。
注:向量vector可以直接比较其中内容是否相等
暴力解法:会超时
sort函数:数组:sort(数组名称,数组名称+数组长度)
向量,字符串:sort(名称.begin(),名称.end())
substr函数:str.substr(开始位置,长度)
vector<int> findAnagrams(string s, string p) {
vector<int> sc(26), pc(26);
vector<int> res;
if (s.length() >= p.length()) {
for (int i = 0; i < p.length(); i++) {
sc[s[i] - 'a']++;
pc[p[i] - 'a']++;
}
int i = 0;
for (i = 0; i < s.length() - p.length(); i++) {
if (sc == pc)
res.push_back(i);
sc[s[i] - 'a']--;
sc[s[i + p.length()] - 'a']++;
}
if (sc == pc)
res.push_back(i);
}
return res;
}
十、560:和为K的子数组(哈希前缀和,中等)
思路:利用前缀和,即求sum[j]-sum[i]=k,即满足sum[i]=sum[j]-k(必须满足j>i)。一次循环,一边计算前缀和,一边遍历前缀和。使用map来保存当前第i个数之前的前缀和每个值出现的次数
注:直接二重循环会超时
int subarraySum(vector<int>& nums, int k) {
map<int, int> mp;
int sum = 0;
int res = 0;
mp[0] = 1;
for (int i = 0; i < nums.size(); i++) {
sum += nums[i];
if (mp.find(sum - k) != mp.end()) {
res += mp[sum - k];
}
mp[sum]++;
}
return res;
}
11、239:滑动窗口最大值(优先队列,困难)
思路:使用优先队列来寻找每个滑动窗口内的最大值。
优先队列需要记录向量中的值和其下标:pair<int,int>
首先将前k个数放入优先队列,队头为当前的最大值;然后右移一位,把数放入队列, 同时需要利用while循环,判断当前队头是否在滑动窗口内部;
若不在,则该队头可以移出去,因为随着窗口不断右移,该数一定不在滑动窗口内部。
若在,则该数为当前滑动窗口内的最大值。
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int> res;
priority_queue<pair<int, int>> pq;
for (int i = 0; i < k; i++) {
pq.push({nums[i], i});
}
res.push_back(pq.top().first);
for (int i = k; i < nums.size(); i++) {
pq.push({nums[i], i});
while (pq.top().second < i - k + 1) {
pq.pop();
}
res.push_back(pq.top().first);
}
return res;
}
12、最小覆盖字串(滑动窗口哈希,困难)
思路: 使用两个哈希表来保存字符串中每个字母出现的次数,这里使用数组实现,tt保存t中次数,ss保存s的字串中每个字母出现的次数。使用滑动窗口,两个指针l,r最初都指向开头,移动r,将r指向的字母出现次数加一,然后判断此时l和r之间的字串是否覆盖t(覆盖即指s中每个字母出现的次数一定要大于等于t中的)。
若覆盖,则进入while循环,判断此时字串的长度,若小于现在resl到resr的值,则更新resl和resr的值;然后将指针l所指的字母出现的次数减一,l加一,直到不在覆盖时跳出while循环。
最后要利用一个标志flag来判断是否进入while循环,若从未进入,则表示s中不包含t,返回空字符串;否则返回最短字串。
大小写字母的ascii之间还有几个不是字母,A:65-90,a:97-122
bool is_cover(int ss[], int tt[]) {
for (int i = 0; i < 58; i++) {
if (ss[i] < tt[i])
return false;
}
return true;
}
string minWindow(string s, string t) {
int ss[58], tt[58];
for (int i = 0; i < t.size(); i++)
tt[t[i] - 'A']++;
int l = 0, r = 0;
int resl = 0, resr = s.size();
int flag = 0;
for (int r = 0; r < s.size(); r++) {
ss[s[r] - 'A']++;
while (is_cover(ss, tt)) {
flag++;
if (resr - resl >= r - l + 1) {
resl = l;
resr = r;
}
ss[s[l] - 'A']--;
l++;
}
}
if (flag >= 1)
return s.substr(resl, resr - resl + 1);
else
return "";
}
Python:
Counter 是 dict 字典的子类,键为待计数的元素, value 为对应元素出现的次数。
a=Counter(空/dict/list/string/tuple)
如果在 Counter 中查找一个不存在的元素,会返回 0;而字典会抛出异常
Counter之间支持加、减、交、并、比较运算(不存在的元素用0比较)
def minWindow(self, s: str, t: str) -> str:
td = Counter(t) # 以字典的形式保存t中每个字母出现的次数
sd = Counter() # 创建一个空的
resl, resr = 0, len(s)
l = 0
flag = 0
for r, ch in enumerate(s): # 同时取出位置索引和对应的值
sd[ch] += 1
while sd >= td:
flag = 1
if resr - resl >= r - l + 1:
resl, resr = l, r
sd[s[l]] -= 1
l += 1
if flag == 1:
return s[resl : resr + 1]
else:
return ""
13、53:最大子数组和(动态规划,中等)
思路:动态规划dp(i)=max(dp(i-1)+nums[i],nums[i])
一个数字,要么单独作为一段即从该数字开始算,要么加入前一个数的队列当中,必然选择两种方案中值最大的那种方案。
int maxSubArray(vector<int>& nums) {
int res = nums[0], temp = 0;
for (int i = 0; i < nums.size(); i++) {
temp = max(temp + nums[i], nums[i]);
res = max(res, temp);
}
return res;
}
Python:
def maxSubArray(self, nums: List[int]) -> int:
res=nums[0]
temp=0
for num in nums:
temp=max(temp+num,num)
res=max(res,temp)
return res
14、56:合并区间(排序,中等)
思路:题目与下标位置无关,不管有没有用,要能想到排序
首先按区间左端点的大小进行排序,让l,r指向第一个区间的左右端点,然后遍历每个区间。若当前区间的左端点小于等于r,则可以合并,令r为r和当前区间右端点中较大的值;
否则,可以将此时的l和r加入到结果中,因为已经排过序,若这个左端点大于r,表示后面的所有区间的左端点都大于r,不会再有能与l和r合并的区间。并更新l和r为当前区间的左右端点。
vector<vector<int>> merge(vector<vector<int>>& intervals) {
vector<vector<int>> res;
sort(intervals.begin(),intervals.end());
int l=intervals[0][0],r=intervals[0][1];
for(int i=1;i<intervals.size();i++){
if(intervals[i][0]<=r){
r=max(r,intervals[i][1]);
}
else{
res.push_back({l,r});
l=intervals[i][0];
r=intervals[i][1];
}
}
res.push_back({l,r});
return res;
}
Python:
def merge(self, intervals: List[List[int]]) -> List[List[int]]:
intervals.sort()
res = []
l = intervals[0][0]
r = intervals[0][1]
for interval in intervals[1:]:
if interval[0] <= r:
r = max(r, interval[1])
else:
res.append([l, r])
l = interval[0]
r = interval[1]
res.append([l, r])
return res
15、189:轮转数组(中等)
思路:空间复杂度O(n):循环向右移动k位
空间复杂度O(1):先整体翻转,然后翻转前k个,翻转剩下的
void rotate(vector<int>& nums, int k) {
int len=nums.size();
vector<int> temp(len);
for(int i=0;i<nums.size();i++){
temp[(i+k)%len]=nums[i];
}
nums=temp;
}
void rotate(vector<int>& nums, int k) {
//空间复杂都O(1)做法,即原地反转
//先整体全部反转,然后再分别反转前k个和后len-k个
//C++反转函数:reverse(开头位置,结尾位置)
k=k%nums.size();
reverse(nums.begin(),nums.end());
reverse(nums.begin(),nums.begin()+k);
reverse(nums.begin()+k,nums.end());
}
Python:
def rotate(self, nums: List[int], k: int) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
def reverse(i,j):
while i<j:
nums[i],nums[j]=nums[j],nums[i]
i+=1
j-=1
k=k%len(nums)
reverse(0,len(nums)-1)
reverse(0,k-1)
reverse(k,len(nums)-1)
16、238:除自身以外数组的乘积(前缀和,中等)
思路:题干说不要用除法,但用除法过了😂😂😂😂就是算出所有乘积,然后除以当前的数。要注意0的个数,所以使用flag来统计0的个数,flag=0则正常除;flag=1则有一个零,因此不是0的数结果都为0,0的结果为除0之外的乘积;flag=2,则结果都是0
前缀和解法:每一个数的结果为它左边的乘积*右边的乘积,所有用两个前缀和,分别为从左边开始的乘积,从右边开始的乘积
vector<int> productExceptSelf(vector<int>& nums) {
vector<int> res;
int flag = 0, ans =1;
for (int i = 0; i < nums.size(); i++) {
if (nums[i] == 0) {
flag++;
} else {
ans *= nums[i];
}
}
if (flag == 0) {
for (int i = 0; i < nums.size(); i++)
res.push_back(ans / nums[i]);
} else if (flag == 1) {
for (int i = 0; i < nums.size(); i++) {
if (nums[i] == 0)
res.push_back(ans);
else
res.push_back(0);
}
} else {
for (int i = 0; i < nums.size(); i++)
res.push_back(0);
}
return res;
}
vector<int> productExceptSelf(vector<int>& nums) {
//前缀和解法
int len=nums.size();
int l[len],r[len];
l[0]=nums[0];
r[len-1]=nums[len-1];
vector<int> res;
for(int i=1;i<len;i++){
l[i]=l[i-1]*nums[i];
r[len-1-i]=nums[len-1-i]*r[len-i];
}
for(int i=0;i<nums.size();i++){
if(i==0) res.push_back(r[i+1]);
else if(i==len-1) res.push_back(l[len-2]);
else{
res.push_back(l[i-1]*r[i+1]);
}
}
return res;
}
def productExceptSelf(self, nums: List[int]) -> List[int]:
ans=[1]*(len(nums))
temp=1
for i in range(1,len(nums)):
temp*=nums[i-1]
ans[i]=temp
temp=1
for i in range(len(nums)-2,-1,-1):
temp*=nums[i+1]
ans[i]=ans[i]*temp
return ans
17、缺失的第一个正数(哈希,困难)
思路:空间复杂度O(n):使用标志数组长度+2的额外空间,初始化为0,若数组中的数在1到n之间,则将相应的标志数组加一。然后遍历标志数组,找出第一个值为0的下标,即为结果。
空间复杂度O(1):由于只考虑1到n中的数,因此可以先遍历,把不在1到n内的数修改成任意一个大于 N 的数(例如 N+1)。此时数组中的所有数就都是正数了,就可以将标记表示为负号。
int firstMissingPositive(vector<int>& nums) {
int n=nums.size();
int f[n+2];
memset(f,0,sizeof(f));
for(int i=0;i<n;i++){
if(nums[i]>=1&&nums[i]<=n){
f[nums[i]]++;
}
}
int res=0;
for(int i=1;i<=n+1;i++){
if(f[i]==0){
res=i;
break;
}
}
return res;
}
def firstMissingPositive(self, nums: List[int]) -> int:
flag=[0]*(len(nums)+1)
for i in nums:
if i>0 and i<=len(nums):
flag[i]=1
for i in range(1,len(flag)):
if flag[i]==0:
return i
return len(flag)
18 、73:矩阵置零(哈希,中等)
思路:使用集合来记录数组中含有0的列。遍历数组每一个元素,先行后列,每次开始新一行遍历时要设一个标志变量来记录该行中是否有数组。
对于每一行,若存在为0的数则将标志变量置位1,同时把列插入到集合中;一行遍历结束后,若标志变量为1,则说明该行存在0,将整行置零。
最后遍历集合,将每列置0。
void setZeroes(vector<vector<int>>& matrix) {
set<int> column;
int m = matrix.size(), n = matrix[0].size();
for (int i = 0; i < m; i++) {
int flag = 0;
for (int j = 0; j < n; j++) {
if (matrix[i][j] == 0) {
flag = 1;
column.insert(j);
}
}
if (flag == 1) {
for (int k = 0; k < n; k++)
matrix[i][k] = 0;
}
}
set<int>::iterator it;
for (it = column.begin(); it != column.end(); it++) {
for (int i = 0; i < m; i++) {
matrix[i][*it] = 0;
}
}
}
19、54:螺旋矩阵(中等)
思路:就是找规律
或者搜索,按照右、下、左、上的顺序搜索,并设置标记数组,当全部访问过一遍时结束。
vector<int> spiralOrder(vector<vector<int>>& matrix) {
vector<int> res;
int m = matrix.size(), n = matrix[0].size();
for (int i = 0; i < (min(m, n) + 1) / 2; i++) {
for (int j = i; j < n - i; j++) {
res.push_back(matrix[i][j]);
}
for (int j = i + 1; j < m - i; j++) {
res.push_back(matrix[j][n - 1 - i]);
}
for (int j = n - 2 - i; j >= i && (m - 1 - i != i); j--) {
res.push_back(matrix[m - 1 - i][j]);
}
for (int j = m - 2 - i; j >= i + 1 && (n - 1 - i != i); j--) {
res.push_back(matrix[j][i]);
}
}
return res;
}
vector<int> spiralOrder(vector<vector<int>>& matrix) {
int dir[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
vector<int> res;
int m = matrix.size(), n = matrix[0].size();
int sum = m * n;
int visited[m][n];
memset(visited, 0, sizeof(visited));
int row = 0, column = 0;
int dirindex = 0;
for (int i = 0; i < sum; i++) {
res.push_back(matrix[row][column]);
visited[row][column] = 1;
int nextrow = row + dir[dirindex][0],
nextcolumn = column + dir[dirindex][1];
if (nextrow < 0 || nextrow >= m || nextcolumn < 0 ||
nextcolumn >= n || visited[nextrow][nextcolumn] == 1) {
dirindex = (dirindex + 1) % 4;
}
row += dir[dirindex][0];
column += dir[dirindex][1];
}
return res;
}
class Solution:
def setZeroes(self, matrix: List[List[int]]) -> None:
"""
Do not return anything, modify matrix in-place instead.
"""
m = len(matrix)
n = len(matrix[0])
rowHasZero = []
colHasZero = []
for i in range(0, m):
for j in range(0, n):
if matrix[i][j] == 0:
rowHasZero.append(i)
colHasZero.append(j)
rowHasZero_set = set(rowHasZero)
colHasZero_set = set(colHasZero)
for i in range(0, m):
for j in range(0, n):
if i in rowHasZero_set or j in colHasZero_set:
matrix[i][j] = 0
20、48:旋转图像(中等)
思路:使用一个n*n的辅助空间,第i行变成第n-i-1列,第j列变成第i行。
或者,找到旋转规律。
,四次旋转回到原处,因此用temp暂存matrix[i][j]。二重循环遍历,只需遍历前n/2行,
void rotate(vector<vector<int>>& matrix) {
int n = matrix.size();
vector<vector<int>> temp(n, vector<int>(n));
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
temp[j][n - i - 1] = matrix[i][j];
}
}
matrix = temp;
}
void rotate(vector<vector<int>>& matrix) {
int n = matrix.size();
for (int i = 0; i < n / 2; i++) {
for (int j = i; j < n - 1 - i; j++) {
int temp = matrix[i][j];
matrix[i][j] = matrix[n - j - 1][i];
matrix[n - j - 1][i] = matrix[n - i - 1][n - j - 1];
matrix[n - i - 1][n - j - 1] = matrix[j][n - i - 1];
matrix[j][n - i - 1] = temp;
}
}
}
class Solution:
def rotate(self, matrix: List[List[int]]) -> None:
"""
Do not return anything, modify matrix in-place instead.
"""
m = len(matrix)
temp, temp2 = 0, 0
if m % 2 == 0:
n = int(m / 2)
else:
n = int(m / 2) + 1
for i in range(0, n):
for j in range(i, m - i - 1):
temp = matrix[j][m - i - 1]
matrix[j][m - i - 1] = matrix[i][j]
temp2 = matrix[m - i - 1][m - j - 1]
matrix[m - i - 1][m - j - 1] = temp
temp = matrix[m - j - 1][i]
matrix[m - j - 1][i] = temp2
matrix[i][j] = temp
2184

被折叠的 条评论
为什么被折叠?



