目录
删除排序数组中的重复项
买卖股票的最佳时机 II
旋转数组
存在重复元素
只出现一次的数字
两个数组的交集 II
加一
移动零
两数之和
☆【留坑以后再补】☆
有效的数独
☆【留坑以后再补】☆
旋转图像
❤ 2021.8.26 ❤
知道LeetCode这个东西有一两年了,一见到就很有学习的冲动,但是自己太菜,一直做比较简单的硬件开发,没怎么接触过算法数据结构之类的东西,当时选了最简单的第一题就被劝退了,甚至我都不知道答题窗口里的函数结构怎么用。。。
前两天师妹心血来潮要刷LeetCode,我趁机也刷一刷也好有人能讨论讨论。
→→→时光倒流!
❤ 2021.8.24 ❤
今天的题目是
芜湖挺简单的,但是不会。。。
根据我多年来的考研经验,不会的题先背答案再说!
答案是这么说的
嗯。。。很好理解,然后(参考别人的答案)自己写了代码
int removeDuplicates(int* nums, int numsSize)
{
int left = 0;
//双指针法
for (int right = 1; right < numsSize; right++)
{
if (nums[left] != nums[right])
{
nums[++left] = nums[right];
}
}
return ++left;
}
运行,没有问题,提交,得
经过我(对照别人的答案)缜密分析,发现可能是我没考虑空数组的情况于是
int removeDuplicates(int* nums, int numsSize)
{
int left = 0;
//判断数组是否为空
if (numsSize == 0)
return 0;
//双指针法
for (int right = 1; right < numsSize; right++)
{
if (nums[left] != nums[right])
{
nums[++left] = nums[right];
}
}
return ++left;
}
这下没问题了
第一次成功提交答案,纪念一下。。。
再次特别感谢师妹,告诉我验证答案的时候要用printf。。。(用单片机的时候被printf虐待过的人飘过。。。)
另外师妹告诉我在vs里使用c语言需要新建空文件,然后添加源文件手动修改扩展名为.c才是真正用c语言的编译器编译的,学到了学到了。
然后我还看了另一种思路
大概意思就是通过遍历寻找相同项,然后按顺序依次把数组元素修改为相同元素中的最后一项。
感觉没有上一种方法那么好理解,但是异曲同工吧。
❤ 2021.8.25 ❤
今天的题目是
首先吐槽一下这个题目,你家买股票能知道未来n天的价格变化呀你是神仙么?
这次读完题目后我没有立刻查答案,而是先思考了一下。
我的思路是:
首先我把所有情况都计算出来,算出每种买卖方式的能挣到的钱,然后取最大值。
想法很简单,在写代码的时候遇到问题,就是我并不知道题目给出的天数具体有几天,也就是说不知道数组的成员数,可能会有很长的一个数组,于是在写代码的时候不能用for循环,因为不知道需要嵌套几层。我想到用递归的方法去做,但是感觉有点复杂(而且我不会。。。),于是我还是去看了答案。。。
答案有几种思路,第一种是动态规划,用递推公式
有点复杂,大概看懂了,但是代码实现有点复杂,我看了下一种思路。
这个就很有意思了,用下面网友的话说就是
我的理解就是,明天要涨我就买(或手里有股票不操作),明天要跌我就卖(或手里没股票不操作),只要一分不亏,最后一定能得到最大收益。
然后我写了代码
int maxProfit(int* prices, int pricesSize)
{
int iProfit = 0;
if (pricesSize == 0)
return 0;
for (int i = 0; i < pricesSize - 1; i++)
{
int j = prices[i + 1] - prices[i];
if (j > 0)
iProfit = iProfit + j;
}
return iProfit;
}
OK没有问题,提交
喵喵喵?这评分也太低了吧!
不过我还是要吐槽一下,python真香!
❤ 2021.8.26 ❤
今天的题目是
第一眼看到这个题目,我去好简单啊哈哈哈(pia打脸)
我的想法是这样的:
1、最简单的方法当然是建立临时数组,但是内存占用较多,空间复杂度肯定不达标。
2、于是我想到可以每次只移动一位,循环k次。
代码如下
void rotate2(int* nums, int numsSize, int k)
{
int Temp;
if (k == 0)
return 0;
k %= numsSize;
for (int i = 1; i < k + 1; i++)
{
Temp = nums[numsSize - 1];
for (int j = numsSize - 1; j > 0; j--)
{
nums[j] = nums[j - 1];
}
nums[0] = Temp;
}
}
这个代码呢,经过测试是没有问题的,但是。。。
耗时太长了。。。晕
3、于是我换了一种思路,在参考了答案之后,我尝试了这个环形移动的方法
每次替换第ik个元素,当ik超过数组长度时取余,代码如下
void rotate3(int* nums, int numsSize, int k)
{
int Temp1,Temp2;
if (k == 0)
return 0;
k %= numsSize;
Temp1 = nums[0];
for (int i = 0; i < numsSize; i++)
{
Temp2 = nums[((i + 1) * k) % numsSize];
nums[((i + 1) * k) % numsSize] = Temp1;
Temp1 = Temp2;
}
}
但是。。。但是!我遇到了参考答案里说的,数组长度是k的整数倍的问题,答案里说用visit函数,过滤掉已经访问过的元素,但是我不知道在c语言里怎么用,所以pass。。。
4、最后我用了多次反转的方法(这种方法是怎么想出来的!!??)
代码如下
void reverse(int* nums,int start,int end)
{
while (end > start)
{
int temp = nums[start];
nums[start] = nums[end];
nums[end] = temp;
start++;
end--;
}
}
void rotate(int* nums, int numsSize, int k)
{
if (k == 0)
return 0;
k %= numsSize;
reverse(nums, 0, numsSize-1);
reverse(nums, 0, k - 1);
reverse(nums, k, numsSize-1);
}
还要自己写reverse()函数,就挺麻烦。。。
而且我第一次提交的时候没注意reverse()函数和rotate()函数的元素对应问题,提交之后报错了
我就很奇怪,为啥别人的代码和我的差不多,但是速度就比我快了不止一点半点。。。
❤ 2021.8.27 ❤
今天的题目是
看到题目之后第一反应依然是:呵,简单。
然后。。。
WTF!暴力检索方法居然不让用。
然后我想到了先排序再判断的方法,然后就涉及到排序算法的问题,关于排序我只知道冒泡,但是考虑到冒泡排序的效率。。。。。。
然后我就看了答案。
不看不知道,一看吓一跳,他居然直接调用C语言自带的排序函数!
然后我不得不去学习了下这个函数qsort()。
关于这个函数我查到了这位老哥的文章,讲的还挺详细。
C语言qsort函数用法
这个函数比较特别的地方是需要自己定义一个比较函数,然后通过回调函数的形式来调用,实现数组的排序。
在这里用到的是这个函数
int cmp(const void* _a, const void* _b) {
int a = *(int*)_a, b = *(int*)_b;
return a - b;
}
至于为什么这样写,我查了一些资料得出的结论是:就是这样规定的。。。
除此之外当比较的数组类型不同时,需要把比较函数进行相应修改,见老哥文章。
有了这个排序函数之后就非常简单了
int cmp(const void* _a, const void* _b) {
int a = *(int*)_a, b = *(int*)_b;
return a - b;
}
bool containsDuplicate(int* nums, int numsSize)
{
if (numsSize == 0)
return 0;
qsort(nums, numsSize, sizeof(int), cmp);
for (int i = 0; i < numsSize-1; i++)
{
if (nums[i] == nums[i + 1])
return true;
}
return false;
}
好像还不错(不愧是官方答案。。。)
另外在vs环境下调试过程中需要注意想使用bool类型和qsort()函数需要添加对应的头文件
#include
#include
❤ 20210.8.28 ❤
今天的题目是
看到题之后:这题昨天不是做过吗?不就是先排序再检索吗?有难度吗?(pia~!)
int cmp(const void* _a, const void* _b)
{
int a = *(int*)_a, b = *(int*)_b;
return a - b;
}
int singleNumber(int* nums, int numsSize)
{
qsort(nums, numsSize, sizeof(int), cmp);
if (numsSize == 1)
{
return nums[0];
}
else if (numsSize > 1)
{
if (nums[0] != nums[1])
{
return nums[0];
}
else
{
for (int i = 1; i < numsSize - 1; i++)
{
if (nums[i] != nums[i - 1] && nums[i] != nums[i + 1])
return nums[i];
}
return nums[numsSize - 1];
}
}
else
return 0;
}
提交之后我觉得我真是越来越厉害了,完全抓住了命题人的思路哈哈哈。。。
然后我一看答案,傻眼
这TM谁想得到啊!
不过这种方法是真的简单(人和人的差距咋就那么大捏。。。)
int singleNumber(int* nums, int numsSize)
{
for (int i = 1; i < numsSize; i++)
{
nums[0] ^= nums[i];
}
return nums[0];
}
这里需要注意的地方,为了节省存储空间,所以这里用了nums[0]作为存储最终结果的变量,所以for循环要从i=1开始,一开始没注意,结果就错了。
唉。。。
❤ 2021.8.30 ❤
今天的题目是
看完题目之后我没有什么想法。。。。
经过一番思考,我觉得可以这样:
我新建一个数组,然后检索数组2里面有没有数组1的元素,如果有就将其复制到新数组里,为了防止重复检索,把检索过的元素都修改为一个两个数组里不同是存在的数字,检索完成后新数组里就是两个数组的交集。但是怎么找到这个两个数组里都没有的数字呢,我的想法是在检索之前先从0开始遍历两个数组,直到找到一个数两个数组里不同时存在为止。
我觉得想法可行,但是傻傻的。。。
而且在c语言实现函数里有这么一句话:
我查了半天大概明白了,这里需要动态分配新数组的内存空间。
而且c语言这里有一个参数很奇怪,叫“returnSize”,我看了半天别人的答案才明白过来,这个是用户定义的一个参数,用来存放交集数组的长度的。就很奇怪哈,直接return不行么?然后我又一想,好想数组是动态分配的,他的地址也需要传回来,真麻烦。。。
关于动态分配内存,大概是应用malloc() 函数。
使用的话是这样
str = (char *) malloc(15);
根据我查阅资料的深入,我发现有这么几个函数的功能类似
malloc(), calloc()和 realloc() ,关于这几个函数的区别我就不搬了,见这位老哥
malloc()与calloc区别
关于所用的算法,主要有两种,一个是先排序再用双指针法,一个是用map(映射表)。
双指针法还是很好理解的,在排序之后,依次比较两个数组元素的大小,哪个小哪个下标就加一,直到找到相同的元素,并将其存到新数组里。
int cmp(const void* _a, const void* _b)
{
return *(int*)_a - *(int*)_b;
}
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* intersect(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize) {
qsort(nums1, nums1Size, sizeof(int), cmp);
qsort(nums2, nums2Size, sizeof(int), cmp);
*returnSize = 0;
int* intersection = (int*)malloc(sizeof(int) * fmin(nums1Size, nums2Size));
int i1 = 0 , i2 = 0;
while (i1 < nums1Size && i2 < nums2Size)
{
if (nums1[i1] > nums2[i2])
i2++;
else if (nums1[i1] < nums2[i2])
i1++;
else
{
intersection[*returnSize] = nums1[i1];
i1++;
i2++;
(*returnSize)++;
}
}
return intersection;
}
我在调试的时候遇到一个问题
经过我多方比较发现是这里没有加括号。。。
加上括号就没问题了,还是我以前缺少指针使用的经验。
另外函数里使用了fmin()函数,需要添加math.h库。
关于其他的方法,用的是哈希表,map等的方法,这些东西对我来说还有点难度,应用起来有点困难,不过用刻师傅的话说,心有所向,日复一日,必有进益!
set(集合),map(映射表)都属于关联式容器。
来源:关联式容器
还有这个
map和set的概念及使用
然后我又了解了下什么是红黑树
红黑树(RB-Tree)
看完之后虽然还是不太了解,但是以后再看到的话就可以说,嗯,我知道。。。
❤ 2021.8.31 ❤
今天的题目是
我的思路:
就很简单嘛!当年用单片机做时钟的时候这是最基础的问题了哈哈哈!(pia!)
我一开始的想法是,最末尾加一之后判断是否为10,如果超了就改为0并把前一位加一,以前在单片机上就是这么做的。可是我一想,因为数组的位数是不确定的,当我如果判断到最后一位时仍然需要进位,那我整个数组的所有元素都需要往后挪一格,好麻烦呀。
所以我又想,可不可以我先判断出运算后的数字长度,然后再分配内存呢?于是我先把数组存放的数字计算出来,然后+1,然后用除以10的方法判断出其位数,同时得到returnSize的大小,然后分配内存,将数字分别存储到数组里。
代码如下
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* plusOne(int* digits, int digitsSize, int* returnSize){
int temp = 0;
for (int i = 0; i < digitsSize; i++)
{
temp += digits[i] * pow(10, (digitsSize - 1 - i));
}
temp++;
int jixu = temp;
int wei = 1;
if (jixu == 0)
{
*returnSize = 1;
}
else
{
while (jixu != 0)
{
jixu /= 10;
wei++;
}
*returnSize = wei-1;
}
int* returnarray = (int*)malloc(sizeof(int) * (*returnSize));
for (int i = 0; i < (*returnSize); i++)
{
returnarray[i] = temp / pow(10, (*returnSize) - 1 - i);
temp = temp % (int)pow(10, (*returnSize) - 1 - i);
}
return returnarray;
}
在经过几次测试之后没有问题,于是我就提交了,于是就报错了
我经过简单分析,发现是内存溢出了,因为数组比较长,所以int型变量吃不消,然后我又换成long型依然吃不消,于是我觉得这个方法是有问题的。
长整型变量最大可以到这么多,而数组对多有100位。
看来只能用逐位判断的方法了,不过我还是要吐槽一下,测试数组里面有{0}真是很让人烦恼啊。。。
这次的思路是,首先把最后一个元素+1,然后进入倒序循环,判断是否为10,如果是则写为0,并把前一个元素+1,依次循环至下标为1的元素。然后判断下标为0的元素是否为10,如果不是则将数组复制到新数组内,numsSize为digitsSize,如果是则numsSize为digitsSize+1,然后新数组前两位为1和0,从第三位开始复制原数组的第二位。
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* plusOne(int* digits, int digitsSize, int* returnSize){
digits[digitsSize - 1]++;
for (int i = digitsSize - 1; i >0; i--)
{
if (digits[i] == 10)
{
digits[i] = 0;
digits[i-1]++;
}
}
int* returnarray = (int*)malloc(sizeof(int) * (digitsSize + 1));
if (digits[0] == 10)
{
*returnSize = digitsSize + 1;
returnarray[0] = 1;
returnarray[1] = 0;
for (int i = 2; i < (*returnSize); i++)
{
returnarray[i] = digits[i - 1];
}
}
else
{
*returnSize = digitsSize;
for (int i = 0; i < (*returnSize); i++)
{
returnarray[i] = digits[i ];
}
}
return returnarray;
}
通过了!
不过调试的时候遇到了一个小问题,我在第一个for循环的地方一开始写成了i>1,于是造成了循环不会遍历到下标为0的元素,改成i>0或者i=1就好了。
蓝后我看了看别人的代码,和我的大概意思差不多,但是还是有细节不一样的地方
我要吐槽一下,人家的语言都可以直接在原数组上增加删除,为啥c语言不行。。。
❤ 2021.9.1 ❤
今天的题目是
我的思路:
就很简单嘛!这一看就是双指针啊!
话不多说,上代码
void moveZeroes(int* nums, int numsSize) {
int i = 0;
while (i < numsSize && nums[i] != 0)
{
i++;
}
if (i == numsSize)
return 0;
for (int j=i; j < numsSize; j++)
{
if (nums[j] != 0)
{
nums[i] = nums[j];
i++;
}
}
for (int k = i; k < numsSize; k++)
{
nums[k] = 0;
}
return 0;
}
思路就是先找到第一个0的位置,如果没有0就返回,然后把后面非零的逐次替代过去。
一次通过,问题不大
然后我又看了别人的代码,发现我的第一步有点多余,不需要特意去判断第一个0在哪里,直接把非零项覆盖时,如果其前面没有0,则相当于替换自己。
优化代码
void moveZeroes(int* nums, int numsSize) {
int i = 0;
for (int j = 0; j < numsSize; j++)
{
if (nums[j] != 0)
{
nums[i] = nums[j];
i++;
}
}
for (int k = i; k < numsSize; k++)
{
nums[k] = 0;
}
return 0;
}
挡当~!
❤ 2021.9.2 ❤
今天的题目是:
说起来,这道题还有点特殊意义,因为这是我当年第一次接触leetcode时选择的题,然后就被劝退了。。。今天又看到了别有一番滋味。
我的思路:
第一个想到的就是双指针遍历呗,一个一个去计算和,找到为止。
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* twoSum(int* nums, int numsSize, int target, int* returnSize)
{
int i = 0, j = 0;
int* returnarray = (int*)malloc(sizeof(int) * 2);
*returnSize = 2;
for (i = 0; i < numsSize - 1; i++)
{
j = i + 1;
while (j < numsSize)
{
if (nums[i] + nums[j] != target)
j++;
else
{
returnarray[0] = i;
returnarray[1] = j;
return returnarray;
}
}
}
return 0;
}
一次通过,耶!
之前一直都在用c语言的方法来解决,但是看到很多稍微复杂一点的方法,c语言实现起来就很麻烦,相对来说C++和python实现起来就很顺滑。。。于是今天先来尝试一下C++。
class Solution {
public:
vector twoSum(vector& nums, int target) {
int i = 0, j = 0;
for (i = 0; i < nums.size() - 1; i++)
{
j = i + 1;
while (j < nums.size())
{
if (nums[i] + nums[j] != target)
j++;
else
{
return { i,j };
}
}
}
return {};
}
};
不得不说代码确实简介了很多
执行时间也慢了很多。。。
还有需要注意的是c++调试的时候用vs要这样调用
#include
#include
using namespace std;
class Solution {
public:
vector twoSum(vector& nums, int target) {
int i = 0, j = 0;
for (i = 0; i < nums.size() - 1; i++)
{
j = i + 1;
while (j < nums.size())
{
if (nums[i] + nums[j] != target)
j++;
else
{
return { i,j };
}
}
}
return {};
}
};
int main()
{
vector a = { 2,7,11,15 };
int target = 9;
Solution S;
vector k = S.twoSum(a, target);
for (int i = 0; i < k.size(); i++)
{
cout << k[i] << "," ;
}
}
然后c++里面好像不用普通的数组,而是用vector来建立数组,相对来说能省很多麻烦。
关于vectorC++ vector 容器浅析
然后我还试了python,但是python我基本不会,所以这是抄来的代码
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
n = len(nums)
for i in range(n):
for j in range(i + 1,n):
if nums[i] + nums[j] == target:
return[i,j]
return []
python的解题代码有了,但是怎么在电脑上测试成了问题。再咨询过张仕政大神之后知道了大概是得这样
from typing import List
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
n = len(nums)
for i in range(n):
for j in range(i + 1,n):
if nums[i] + nums[j] == target:
return[i,j]
return []
if __name__ == '__main__':
list1 = [1, 2, 3, 4, 5]
target = 3
inst = Solution()
print(inst.twoSum(list1, target))
学到了学到了。
另外,今天这道题的进阶版是使用哈希表来完场,我简单了解了下
数据结构 Hash表(哈希表)
哈希表(散列表)原理详解
哈希表的原理及实现代码
嗯,了解完了,下面是抄答案时间
❤ 2021.9.3 ❤
今天的题目是
这题看起来还挺复杂的,我遇到的第一个问题就是在vs里面表示这个二维数组。
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"]]
经过师妹提醒, 要写成单引号
char a[9][9] =
{
{ '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' }
};
然后呢数组有点大啊,就没啥思路,于是不得不看答案。。。
一看答案豁然开朗,没什么是暴力方法不能解决的,用多重循环依次遍历每个元素的横、竖、小方块内是否有和他相同数值的元素就可以了,需要注意的是检索小方块内时注意for循环的其实数值和判定条件的。
bool isValidSudoku(char** board, int boardSize, int* boardColSize)
{
for (int i = 0; i < boardSize; i++)
{
for (int j = 0; j < *boardColSize; j++)
{
if (board[i][j] != '.')
{
for (int x = 0; x < boardSize; x++)
{
if (x != i && board[i][j] == board[x][j])
return false;
}
for (int y = 0; y < *boardColSize; y++)
{
if (y != j && board[i][j] == board[i][y])
return false;
}
//这里注意初始值
for (int z1 = i / 3 * 3; z1 < i / 3 * 3 + 3; z1++)
{
for (int z2 = j / 3 * 3; z2 < j / 3 * 3 + 3; z2++)
{
if (z1 != i && z2 != j && board[i][j] == board[z1][z2])
return false;
}
}
}
}
}
return true;
}
哦哟成绩还不错。
相对于这道题的解法,我觉得我受益更大的是摸索到了二维数组的调用方法。
这道题的数组是通过一个char**变量来传递的,也就是一个指向字符串型指针的指针。最开始我直接把二维数组的地址传递给函数,然后就报错了,经过查阅资料终于搞清楚怎么回事,感谢以下几位老哥
C语言函数传递二维数组
深入 理解char * ,char ** ,char a[ ] ,char *a[] 的区别
我的c语言测试函数是这样的
int main()
{
char a[9][9] =
{
{ '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' }
};
int b = 9;
int c = 9;
char* p[9];
for (int i = 0; i < c; i++)
{
p[i] = a[i];
}
bool k = isValidSudoku(p, b, &c);
printf("%d", k);
}
这里还要吐槽下原题,既然 boardSize是int,为啥boardColSize就变成了int*。。。。
通过使用c语言和暴力检索方法,虽然完成了任务,但是不完美,我在查看答案的过程中看到了应用哈希表思想的解法,于是用c++试着实现了下
class Solution {
public:
bool isValidSudoku(vector>& board) {
unordered_map hashtable;
//初始值很重要
int check[3][9][9] = { 0 };
for (int i = 0; i < 9; i++)
{
for (int j = 0; j < 9; j++)
{
if (board[i][j] != '.')
{
if ((++check[0][board[i][j] - '1'][i] > 1) ||
(++check[1][board[i][j] - '1'][j] > 1) ||
(++check[2][board[i][j] - '1'][(i / 3) * 3 + j / 3] > 1))
return false;
}
}
}
return true;
}
};
当然这段代码是抄来的,因为我觉得就很巧妙。
首先他用了哈希表的思想,但是又没有完全用哈希表,思想就是先建立3个新数组,把原数组按行、列、块分别将数值与下标对应。在遍历过程中,当遇到一个数值时对所在新数组对应元素+1,并判断改数值是否已经被记录过,如果被记录过(>1),则返回false。
另外,c++的调用函数也简单了很多(真香)
int main()
{
vector> a =
{
{ '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' }
};
Solution S;
bool k = S.isValidSudoku(a);
cout << k;
}
关于c++用vector建立的二维数组如何查看长度,见
C++ vector二维数组初始化以及获取数组长度
然后关于用python的解法
❤ 2021.9.4 ❤
今天的题目是
看完题之后我的感觉就是。。。没啥思路,以前在matlab里面旋转图像那不就是一个指令的事情?现在自己搞还有点不知所措。
思考之后我的想法是找规律,然后一个一个的去替换,但是找了半天没找到,焦灼之下看了答案,我这个想法虽然不算是巧妙但也是能够实现的方法,至于规律这位老哥总结的很好
再一看我发现这个规律也不是那么难找
变换之后的i是原来的j,原来的i和现在的j相加为n-1,嘿嘿。。。
上代码
开始我傻了,想要一个一个去去交换,但是这样是不对的
void rotate(int** matrix, int matrixSize, int* matrixColSize) {
int temp1 = 0, temp2 = 0;
int n = matrixSize;
temp2 = matrix[0][0];
for (int i = 0; i < matrixSize; i++)
{
for (int j = 0; j < *matrixColSize; j++)
{
temp1=matrix[j][n - 1 - i];
matrix[j][n - 1 - i] = temp2;
temp2 = temp1;
}
}
matrix[0][0] = temp2;
return 0;
}
经过思考加上看答案,其实每次旋转一定是4个一起转,同时遍历只需要进行四分之一个矩阵(奇偶区别就是多一行)
void rotate(int** matrix, int matrixSize, int* matrixColSize) {
int temp;
int n = matrixSize;
for (int i = 0; i < (n+1)/2; i++)
{
for (int j = 0; j < n / 2; j++)
{
temp = matrix[i][j];
matrix[i][j] = matrix[n - 1 - j][i];
matrix[n - 1 - j][i] = matrix[n - 1 - i][n - 1 - j];
matrix[n - 1 - i][n - 1 - j] = matrix[j][n - 1 - i];
matrix[j][n - 1 - i] = temp;
}
}
return 0;
}
提交
此外还有先绕水平轴翻转,再绕对角线翻转的解法,就挺神奇的。
另外,用python的大佬给出了非常简短的解法,今天时间有限就不去探究了