目录
LeetCode 初级算法-数组链接:https://leetcode-cn.com/leetbook/read/top-interview-questions-easy/x2i30g/
一、删除排序数组中的重复项
给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
示例 1:
输入:nums = [1,1,2]
输出:2, nums = [1,2]
解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。
示例 2:输入:nums = [0,0,1,1,1,2,2,3,3,4]
输出:5, nums = [0,1,2,3,4]
解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。不需要考虑数组中超出新长度后面的元素。
1.C
(1)双指针(通用法)
int removeDuplicates(int* nums, int numsSize){
int len = 1, left = 0, right = 1;
//判断数组长度
if(numsSize == 0)
return 0;
//遍历数组
while(right < numsSize)
{
if(nums[left] != nums[right]) //遇到数字不同
{
len++;
//判断之前是否有重复的数字
if(right == left + 1) //无重复
{
left = right;
}
else //有重复
{
nums[left + 1] = nums[right];
left++;
}
}
right++;
}
return len;
}
(2)快慢指针
int removeDuplicates(int* nums, int numsSize){
int slow = 1, fast = 1;
//判断数组长度
if(numsSize == 0)
return 0;
//遍历数组 fast用于遍历整体数组,slow用于记录不重复数字
while(fast < numsSize)
{
if(nums[fast] != nums[fast - 1])
{
nums[slow] = nums[fast];
slow++;
}
fast++;
}
return slow;
}
2.Python
(1)快慢指针
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
# 判断数组长度
n = len(nums)
if not n:
return 0
# 遍历数组:fast用于遍历数组,slow用于记录不重复数字
fast = slow = 1
while fast < n:
if nums[fast] != nums[fast - 1]:
nums[slow] = nums[fast]
slow += 1
fast += 1
return slow
二、买卖股票的最佳时机 II
给定一个数组 prices ,其中 prices[i] 是一支给定股票第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
示例 1:
输入: prices = [7,1,5,3,6,4]
输出: 7
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6-3 = 3 。
示例 2:输入: prices = [1,2,3,4,5]
输出: 4
解释: 在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。
示例 3:输入: prices = [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。
1.C
(1)动态规划
int Max(int a, int b)
{
return (a > b)? a : b;
}
int maxProfit(int* prices, int pricesSize){
//动态规划:
//设计状态:x天手中没有股票最大利润 dp[x][0]
// x天交易完后手中持有一支股票最大收益dp[x][1]
//状态转移方程:dp[x][0] = max{dp[x-1][0], dp[x-1][1]+prices[x]}
// dp[x][1] = max{dp[x-1][1], dp[x-1][0]-prices[x]}
if(pricesSize == 0)
return 0;
int dp[pricesSize][2], max = 0;
dp[0][0] = 0; //第1天手中没有股票最大利润为0
dp[0][1] = -prices[0]; //第1天手中有1支股票最大利润为-prices[0]
for(int i = 1; i < pricesSize; i++)
{
dp[i][0] = Max(dp[i-1][0], dp[i-1][1]+prices[i]);
dp[i][1] = Max(dp[i-1][1], dp[i-1][0]-prices[i]);
}
return dp[pricesSize-1][0];
}
(2)贪心算法
int Max(int a, int b)
{
return (a > b)? a : b;
}
int maxProfit(int* prices, int pricesSize){
//贪心算法:(局部问题的最优解)
//将交易跨度定为隔天,当天买,隔天卖。求以1天为长度的最大利润
int max = 0;
for(int i = 0; i < pricesSize - 1; i++)
max += Max(0, prices[i+1] - prices[i]);
return max;
}
2.Python
(1)动态规划
class Solution:
def maxProfit(self, prices: List[int]) -> int:
pricesSize = len(prices)
if not pricesSize:
return 0
dp = [[0]*2 for _ in range(pricesSize)]
dp[0][0] = 0
dp[0][1] = -prices[0]
for i in range(1, pricesSize):
dp[i][0] = max(dp[i-1][0], dp[i-1][1]+prices[i])
dp[i][1] = max(dp[i-1][1], dp[i-1][0]-prices[i])
return dp[pricesSize - 1][0]
(2)贪心算法
class Solution:
def maxProfit(self, prices: List[int]) -> int:
pricesSize = len(prices)
if not pricesSize:
return 0
profit = 0
for i in range(pricesSize-1):
profit += max(0, prices[i+1] - prices[i])
return profit
三、旋转数组
给你一个数组,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。
示例 1:
输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右轮转 1 步: [7,1,2,3,4,5,6]
向右轮转 2 步: [6,7,1,2,3,4,5]
向右轮转 3 步: [5,6,7,1,2,3,4]
示例 2:输入:nums = [-1,-100,3,99], k = 2
输出:[3,99,-1,-100]
解释:
向右轮转 1 步: [99,-1,-100,3]
向右轮转 2 步: [3,99,-1,-100]。
1.C
(1)额外数组
//1.使用额外数组
void rotate(int* nums, int numsSize, int k){
int newNums[numsSize];
for(int i = 0; i < numsSize; i++)
newNums[(i+k)%numsSize] = nums[i];
for(int i = 0; i < numsSize; i++)
nums[i] = newNums[i];
}
(2)翻转法
void reversal(int *nums, int numsSize)
{
for(int i = 0; i < (numsSize / 2); i++)
{
int temp = nums[i];
nums[i] = nums[numsSize - 1 - i];
nums[numsSize - 1 - i] = temp;
}
}
void rotate(int* nums, int numsSize, int k){
int rotate_k = k % numsSize;
reversal(nums, numsSize);
reversal(nums, rotate_k);
reversal(nums + rotate_k, numsSize - rotate_k);
}
2.Python
(1)额外数组(列表)
class Solution:
def rotate(self, nums: List[int], k: int) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
length = len(nums)
newNums = [0]*length
for i in range(length):
newNums[(i+k)%length] = nums[i]
nums[:] = newNums
(2)切片
class Solution:
def rotate(self, nums: List[int], k: int) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
length = len(nums)
k = k % length
nums[:] = nums[length - k:] + nums[:length - k]
四、存在重复元素
给你一个整数数组 nums 。如果任一值在数组中出现 至少两次 ,返回 true ;如果数组中每个元素互不相同,返回 false 。
示例 1:
输入:nums = [1,2,3,1]
输出:true
示例 2:输入:nums = [1,2,3,4]
输出:false
示例 3:输入:nums = [1,1,1,3,3,4,3,2,4,2]
输出:true
1.C
(1)快慢指针
int cmp(const void *a, const void *b)
{
return *(int *)a - *(int *)b;
}
bool containsDuplicate(int* nums, int numsSize){
if(numsSize <= 1)
return false;
qsort(nums, numsSize, sizeof(int), cmp);
int slow = 0, fast = 1;
while(fast < numsSize)
{
if(nums[slow] != nums[fast])slow = fast;
else return true;
fast++;
}
return false;
}
(2)哈希表(开源哈希表)
typedef struct hashTable_t{
int key;
UT_hash_handle hh;
}hashTable_t;
bool containsDuplicate(int* nums, int numsSize){
hashTable_t *set = NULL;
for(int i = 0; i < numsSize; i++)
{
hashTable_t *tmp;
HASH_FIND_INT(set, &nums[i], tmp);
if(tmp == NULL)
{
tmp = (hashTable_t *)malloc(sizeof(hashTable_t));
if(tmp != NULL)
{
tmp->key = nums[i];
HASH_ADD_INT(set, key, tmp);
}
}
else
return true;
}
return false;
}
2.Python
(1)集合set的使用(一)
class Solution:
def containsDuplicate(self, nums: List[int]) -> bool:
numsSet = set()
for i in nums:
if i in numsSet:
return True
else:
numsSet.add(i)
return False
(2)集合set的使用(二)
class Solution:
def containsDuplicate(self, nums: List[int]) -> bool:
return len(nums) != len(set(nums))
五、只出现一次的数字
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:
输入: [2,2,1]
输出: 1
示例 2:输入: [4,1,2,1,2]
输出: 4
1.C
(1)暴力解法
int cmp(const void *a, const void *b)
{
return *(int *)a - *(int *)b;
}
int singleNumber(int* nums, int numsSize){
qsort(nums, numsSize, sizeof(int), cmp);
//排序后,只出现一次的元素必定在奇数位
int flag = 0;
for(int i = 0; i < numsSize; i+=2)
{
//判断前后是否存在相同元素
if(i-1>=0)
{
if(nums[i-1] != nums[i]) flag |= 1;
else flag = 0;
}
if(i+1 < numsSize)
{
if(nums[i+1] != nums[i]) flag |= 1;
else flag = 0;
}
if(flag)
return nums[i];
}
return nums[0];
}
(2)异或解法(利用异或特性)
位异或:相同为0,不同为1;
异或:0异或任意数为任意数(如:0^5 = 5)
任意数与自身做运算结果为0(5^5 = 0)
一个数异或偶数个相同数还是等于原值(如:1 ^ 5 ^ 6 ^ 5 ^ 6 = 1;有点类似取反)
int singleNumber(int* nums, int numsSize){
int res = 0;
for(int i = 0; i < numsSize; i++)
res ^= nums[i];
return res;
}
2.Python
(1)异或解法
class Solution:
def singleNumber(self, nums: List[int]) -> int:
return reduce(lambda x, y: x^y, nums)
六、两个数组的交集 II
给你两个整数数组 nums1 和 nums2 ,请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数,应与元素在两个数组中都出现的次数一致(如果出现次数不一致,则考虑取较小值)。可以不考虑输出结果的顺序。
示例 1:
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2,2]
示例 2:输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[4,9]提示:
1 <= nums1.length, nums2.length <= 1000
0 <= nums1[i], nums2[i] <= 1000
1.C
(1)哈希表
int* intersect(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize){
int resSize = (nums1Size > nums2Size)? nums2Size: nums1Size;
int *res = (int *)malloc(sizeof(int) * resSize);
int map1[1001] = {0}, map2[1001] = {0}, len = 0;
for(int i = 0; i < nums1Size; i++)
map1[nums1[i]]++;
for(int i = 0; i < nums2Size; i++)
map2[nums2[i]]++;
for(int i = 0; i < 1001; i++)
{
int map1_cnt = map1[i];
int map2_cnt = map2[i];
if(map1_cnt > 0 && map2_cnt > 0)
{
int cnt = (map1_cnt >= map2_cnt)? map2_cnt : map1_cnt;
for(int j = 0; j < cnt; j++)
res[len++] = i;
}
}
*returnSize = len;
return res;
}
(2)排序+双指针
int cmp(const void *a, const void *b)
{
return *(int *)a - *(int *)b;
}
int* intersect(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize){
int resSize = (nums1Size > nums2Size)? nums2Size : nums1Size;
int *res = (int *)malloc(sizeof(int) * resSize);
qsort(nums1, nums1Size, sizeof(int), cmp);
qsort(nums2, nums2Size, sizeof(int), cmp);
int index1 = 0, index2 = 0, len = 0;
while(index1 < nums1Size && index2 < nums2Size)
{
if(nums1[index1] < nums2[index2])
index1++;
else if(nums1[index1] > nums2[index2])
index2++;
else
{
res[len++] = nums1[index1];
index1++;
index2++;
}
}
*returnSize = len;
return res;
}
(3)暴力解法
//1.从短的数组 进行检索,所以只需要一个指针
int cmp(const void *a, const void *b)
{
return *(int *)a - *(int *)b;
}
int* intersect(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize){
int longSize = (nums1Size > nums2Size)? nums1Size : nums2Size;
int shortSize = (nums1Size > nums2Size)? nums2Size : nums1Size;
int *res = (int *)malloc(sizeof(int) * shortSize);
qsort(nums1, nums1Size, sizeof(int), cmp);
qsort(nums2, nums2Size, sizeof(int), cmp);
int index = 0, len = 0;
for(int i = 0; i < shortSize; i++)
{
for(int j = index; j < longSize; j++)
{
if((nums1Size >= nums2Size) && (nums1[j] == nums2[i]))
{
res[len++] = nums1[j];
index = j+1;
break;
}
else if((nums1Size < nums2Size) && (nums1[i] == nums2[j]))
{
res[len++] = nums2[j];
index = j+1;
break;
}
}
}
*returnSize = len;
return res;
}
2.Python
(1)排序+双指针
class Solution:
def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]:
nums1.sort()
nums2.sort()
res = list()
len1, len2 = len(nums1), len(nums2)
index1 = index2 = 0
while index1 < len1 and index2 < len2:
if nums1[index1] < nums2[index2]:
index1 += 1
elif nums1[index1] > nums2[index2]:
index2 += 1
else:
res.append(nums1[index1])
index1 += 1
index2 += 1
return res
(2)哈希表(字典)
class Solution:
def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]:
if len(nums1) < len(nums2):
return self.intersect(nums2, nums1)
c = collections.Counter(nums2)
res = list()
for i in nums1:
if i in c and c[i] > 0:
res.append(i)
c[i] -= 1
return res
七、加一
给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。
最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。
你可以假设除了整数 0 之外,这个整数不会以零开头。
示例 1:
输入:digits = [1,2,3]
输出:[1,2,4]
解释:输入数组表示数字 123。
示例 2:输入:digits = [4,3,2,1]
输出:[4,3,2,2]
解释:输入数组表示数字 4321。
示例 3:输入:digits = [0]
输出:[1]
提示:
1 <= digits.length <= 100
0 <= digits[i] <= 9
1.C
(1)数学规律
数学规律:逢9变0(找到最长后缀9)
int* plusOne(int* digits, int digitsSize, int* returnSize){
for(int i = digitsSize - 1; i >= 0; i--)
{
if(digits[i] == 9)
digits[i] = 0;
else
{
digits[i]++;
*returnSize = digitsSize;
return digits;
}
}
*returnSize = digitsSize + 1;
int *res = (int *)malloc(sizeof(int) * (digitsSize +1));
memset(res, 0, sizeof(int) * (digitsSize + 1));
res[0] = 1;
return res;
}
2.Python
(1)暴力解法(字符串与整型的转换)
class Solution:
def plusOne(self, digits: List[int]) -> List[int]:
newInt = int(''.join([str(i) for i in digits])) + 1
newList = [int(i) for i in str(newInt)]
return newList
# 整理成一行
class Solution:
def plusOne(self, digits: List[int]) -> List[int]:
return [int(i) for i in str(int(''.join([str(i) for i in digits])) + 1)]
八、移动零
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
示例:
输入: [0,1,0,3,12]
输出: [1,3,12,0,0]
说明:必须在原数组上操作,不能拷贝额外的数组。
尽量减少操作次数。
1.C
(1)快慢指针
void moveZeroes(int* nums, int numsSize){
int slow = 0, fast = 0;
while(fast < numsSize)
{
if(nums[fast] != 0)
{
nums[slow] = nums[fast];
slow++;
}
fast++;
}
for(int i = slow; i < numsSize; i++)
nums[i] = 0;
}
2.Python
(1)列表的删除与添加
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
cnt = 0
while 0 in nums:
nums.remove(0)
cnt += 1
for i in range(cnt):
nums.append(0)
九、两数之和
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:输入:nums = [3,2,4], target = 6
输出:[1,2]
示例 3:输入:nums = [3,3], target = 6
输出:[0,1]
提示:
2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
只会存在一个有效答案
1.C
(1)暴力解法
int* twoSum(int* nums, int numsSize, int target, int* returnSize){
*returnSize = 2;
int *res = (int *)malloc(sizeof(int) * 2);
for(int i = 0; i < numsSize; i++)
{
for(int j = i + 1; j < numsSize; j++)
{
if(nums[i] + nums[j] == target)
{
res[0] = i;
res[1] = j;
return res;
}
}
}
return res;
}
(2) 哈希表
typedef struct hashTable_t {
int id;
int index;
UT_hash_handle hh;
}hashTable_t;
hashTable_t* hashtable;
hashTable_t* find(int id) {
hashTable_t* tmp;
HASH_FIND_INT(hashtable, &id, tmp);
return tmp;
}
void insert(int id, int index) {
hashTable_t* it = find(id);
if (it == NULL)
{
hashTable_t* tmp = malloc(sizeof(hashTable_t));
tmp->id = id;
tmp->index = index;
HASH_ADD_INT(hashtable, id, tmp);
} else
{
it->id = id;
}
}
int* twoSum(int* nums, int numsSize, int target, int* returnSize) {
hashtable = NULL;
for (int i = 0; i < numsSize; i++)
{
hashTable_t* it = find(target - nums[i]);
if (it != NULL) {
int* ret = malloc(sizeof(int) * 2);
ret[0] = it->index;
ret[1] = i;
*returnSize = 2;
return ret;
}
insert(nums[i], i);
}
*returnSize = 0;
return NULL;
}
2.Python
(1)暴力解法
class Solution(object):
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
res = list()
for i in range(len(nums)):
for j in range(i+1, len(nums)):
if nums[i] + nums[j] == target:
res.append(i)
res.append(j)
return res
return res
(2)哈希表(内置字典的使用)
class Solution(object):
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
hashTable = dict()
for i in range(len(nums)):
newTarget = target - nums[i]
if newTarget in hashTable:
return [hashTable[newTarget], i]
hashTable[nums[i]] = i
十、有效的数独
请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 ,验证已经填入的数字是否有效即可。
数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)
注意:
一个有效的数独(部分已被填充)不一定是可解的。
只需要根据以上规则,验证已经填入的数字是否有效即可。
空白格用 '.' 表示。
示例 1:
输入:board =
[["5","3",".",".","7",".",".",".","."]
,["6",".",".","1","9","5",".",".","."]
,[".","9","8",".",".",".",".","6","."]
,["8",".",".",".","6",".",".",".","3"]
,["4",".",".","8",".","3",".",".","1"]
,["7",".",".",".","2",".",".",".","6"]
,[".","6",".",".",".",".","2","8","."]
,[".",".",".","4","1","9",".",".","5"]
,[".",".",".",".","8",".",".","7","9"]]
输出:true示例 2:
输入:board =
[["8","3",".",".","7",".",".",".","."]
,["6",".",".","1","9","5",".",".","."]
,[".","9","8",".",".",".",".","6","."]
,["8",".",".",".","6",".",".",".","3"]
,["4",".",".","8",".","3",".",".","1"]
,["7",".",".",".","2",".",".",".","6"]
,[".","6",".",".",".",".","2","8","."]
,[".",".",".","4","1","9",".",".","5"]
,[".",".",".",".","8",".",".","7","9"]]
输出:false
解释:除了第一行的第一个数字从 5 改为 8 以外,空格内其他数字均与 示例1 相同。 但由于位于左上角的 3x3 宫内有两个 8 存在, 因此这个数独是无效的。提示:
board.length == 9
board[i].length == 9
board[i][j]
是一位数字(1-9
)或者'.'
1.C
(1)哈希表
bool isValidSudoku(char** board, int boardSize, int* boardColSize){
//三种哈希表:行、列、宫
int hash_row[9][10] = {0}, hash_col[9][10] = {0}, hash_Sudoku[9][10] = {0};
//将board种的.换成0
for(int row = 0; row < 9; row++)
{
for(int col = 0; col < 9; col++)
{
if(board[row][col] == '.')
board[row][col] = '0';
}
}
//填充哈希表
//行
for(int row = 0 ; row < 9; row++)
{
for(int i = 0; i < 9; i++)
hash_row[row][board[row][i] - '0']++;
}
//列
for(int col = 0; col < 9; col++)
{
for(int i = 0; i < 9; i++)
hash_col[col][board[i][col] - '0']++;
}
//宫格
for(int i = 0; i < 9; i++)
{
int r = i / 3;
int c = i % 3;
for(int row = r*3; row < r*3+3; row++)
{
for(int col = c*3; col < c*3+3; col++)
hash_Sudoku[i][board[row][col] - '0']++;
}
}
//判断
for(int i = 0; i < 9; i++)
{
for(int j = 1; j <= 9; j++)
{
if(hash_row[i][j] >= 2 || hash_col[i][j] >= 2 || hash_Sudoku[i][j] >= 2)
return false;
}
}
return true;
}
2.Python
(1)字典(哈希表)
class Solution(object):
def isValidSudoku(self, board):
"""
:type board: List[List[str]]
:rtype: bool
"""
hash_row, hash_col, hash_sqrt = defaultdict(set), defaultdict(set), defaultdict(set)
for row in range(9):
for col in range(9):
val = board[row][col]
if val == '.':
continue
point = row // 3 * 3 + col // 3 # 判断在什么宫格
if val in hash_row[row] or val in hash_col[col] or val in hash_sqrt[point]:
return False
hash_row[row].add(val)
hash_col[col].add(val)
hash_sqrt[point].add(val)
return True
十一、旋转图像
给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。
你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。
示例 1:
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[[7,4,1],[8,5,2],[9,6,3]]示例 2:
输入:matrix = [[5,1,9,11],[2,4,8,10],[13,3,6,7],[15,14,12,16]]
输出:[[15,13,2,5],[14,3,4,1],[12,6,8,9],[16,7,10,11]]提示:
- n == matrix.length == matrix[i].length
- 1 <= n <= 20
- -1000 <= matrix[i][j] <= 1000
1.C
(1)找规律
//1.使用额外数组
void rotate(int** matrix, int matrixSize, int* matrixColSize){
if (matrixSize == 1)
return;
int newMatrix[matrixSize][matrixSize];
for(int i = 0; i < matrixSize; i++)
{
for(int j = 0; j < matrixSize; j++)
newMatrix[i][j] = matrix[i][j];
}
for(int i = 0; i < matrixSize; i++)
{
for(int j = 0; j < matrixSize; j++)
matrix[j][matrixSize - i - 1] = newMatrix[i][j];
}
}
//2.原地旋转
void rotate(int** matrix, int matrixSize, int* matrixColSize) {
for (int i = 0; i < matrixSize / 2; ++i) { //需要旋转的点,排除了不需要旋转的中心点
for (int j = 0; j < (matrixSize + 1) / 2; ++j) {
int temp = matrix[i][j];
matrix[i][j] = matrix[matrixSize - j - 1][i];
matrix[matrixSize - j - 1][i] = matrix[matrixSize - i - 1][matrixSize - j - 1];
matrix[matrixSize - i - 1][matrixSize - j - 1] = matrix[j][matrixSize - i - 1];
matrix[j][matrixSize - i - 1] = temp;
}
}
}
2.Python
(1)找规律
# 1.额外列表
class Solution(object):
def rotate(self, matrix):
"""
:type matrix: List[List[int]]
:rtype: None Do not return anything, modify matrix in-place instead.
"""
n = len(matrix)
matrix_new = [[0]*n for _ in range(n)]
for i in range(n):
for j in range(n):
matrix_new[j][n - i - 1] = matrix[i][j]
matrix[:] = matrix_new
# 2.原地旋转
class Solution:
def rotate(self, matrix: List[List[int]]) -> None:
n = len(matrix)
for i in range(n // 2):
for j in range((n + 1) // 2):
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]
小结
涉及数组问题的常见解决方法一般有:双指针(快慢指针)、额外数组(排序)、哈希表。
如果注重时间复杂度则,可以使用 哈希表 、额外数组(排序)等方式,以空间换时间的方式,来减小时间复杂度。
如果注重空间复杂度,则可以使用 双指针 的方式,以时间换空间的方式,来减小空间复杂度。