Leetcode初级算法(排序和搜索+数学篇)
合并两个有序数组
开始的时候将这道题理解错了,发现几个奇怪的测试案例后才明白这道题什么意思。本来的想法就是把nums2全部放到num1里面,然后删除重复元素、排序一下,就有了下面的代码:
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
for(int i=0;i<n;i++)
{
nums1.push_back(nums2[i]);
}
sort(nums1.begin(),nums1.end());
vector<int>::iterator iter = unique(nums1.begin(), nums1.end());
nums1.erase(iter, nums1.end());
}
};
后来发现测试案例是这样给的:[1,2,3,0,0,0] 3 [2,5,6] 3,测试的意思是nums1初始化为【1,2,3,0,0,0】,其中后面三个0是初始化自带的,是要将nums2的元素填充进去。既然这样,呢我们就索性就在原来错误的代码上进行修改吧,无非是只取nums1的前m个元素罢了,更改后的成功代码如下:
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
vector<int> nums(m,0);
for(int i=0;i<m;i++)
{
nums[i]=nums1[i];
}
for(int i=0;i<n;i++)
{
nums.push_back(nums2[i]);
}
sort(nums.begin(),nums.end());
nums1=nums;
}
};
但是这道题感觉自己还是走捷径做出来的,并没有实际上理解想考察哪一个知识点,所以看了大神的代码:
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int end=m+n-1;
m--;n--;
while(m>=0&&n>=0)
{
if(nums2[n]>nums1[m])
{
nums1[end--]=nums2[n--];
}
else
{
nums1[end--]=nums1[m--];
}
}
while(n>=0)
{
nums1[end--]=nums2[n--];
}
}
};
更优一种解法是
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int count=m+n-1;
--m;--n;
while(m>=0 && n>=0) A[count--]=(A[m]>B[n]?A[m--]:B[n--]);
while(n>=0) A[count--]=B[n--];
}
};
第一个错误的版本
第一感觉是二分法,如果最中间的呢个版本出错了,说明错误版本肯定在之前;如果中间版本正确,说明错误版本在之后。所以写成以下代码:
// Forward declaration of isBadVersion API.
bool isBadVersion(int version);
class Solution {
public:
int firstBadVersion(int n) {
if(n<=0) return 0;
int first=1,end=n;
while(first<=end){
int mid=(first+end)/2;
if(isBadVersion(mid))
end=mid-1;
else
first=mid+1;
}
return first;
}
};
但是却显示超时,后来发现可能是int mid=(first+end)/2;
这一行代码出现了问题,因为first+end可能会出现溢出错误,所以改成了一下代码:
// Forward declaration of isBadVersion API.
bool isBadVersion(int version);
class Solution {
public:
int firstBadVersion(int n) {
if(n<=0) return 0;
int first=1,end=n;
while(first<=end){
int mid=first+(end-first)/2;
if(isBadVersion(mid))
end=mid-1;
else
first=mid+1;
}
return first;
}
};
直接就成功了。但是溢出错误却显示超出时间限制,是因为leetcode的代码检测是因为发现溢出没有继续执行导致超出时间限制还是其他原因就不知道了。。。但是通过这道简单的题,一定要了解first+(end-first)/2
与(end+first)/2
在表示上虽然相同,但是计算机计算的时候确实完全不同的!这一点在《C++ Primer》这本书P101的练习3.26上也有验证。
罗马数字转整数
首先了解一下罗马数字是什么;
字母 | M | D | C | L | X | V | I |
---|---|---|---|---|---|---|---|
代表数字 | 1000 | 500 | 100 | 50 | 10 | 5 | 1 |
还有一些具体的规则请见这篇博客
在这里先列举出来,因为对解题还是有帮助的:
1。相同的数字连写,所表示的数等于这些数字相加得到的数。如 XXX表示 30
2.小的数字在大的数字的右边,所表示的数等于这些数字相加得到的数 如VIII 表示8
3.小的数字(限于I, X,C)在大的数字的左边, 所表示的数等于大数减去小的数: 如IV 表示4
4.在一个数的上面画一条横线,表示这个数增值1000倍
注意,并不是将罗马数字所代表的数字加起来就行了,而是需要遵守一定的规则,尤其是第三条。下面放上代码:
class Solution {
public:
int romanToInt(string s) {
unordered_map<char,int> m{{'I',1},{'V',5},{'X',10},{'L',50},{'C',100},{'D',500},{'M',1000}};
int sum=0;
for(int i=0;i<s.size();i++)
{
int val=m[s[i]];
if(i==s.size()-1 || m[s[i+1]]<=m[s[i]]) sum+=val;
else
sum-=val;
}
return sum;
}
};
3的幂
最简单的就是写一个循环进行判断,所以我也这么干了。我的代码
class Solution {
public:
bool isPowerOfThree(int n) {
if(n==0) return false;
while(n%3==0)
{
n=n/3;
}
return n==1;
}
};
但是,题目的进阶要求是不使用循环或者递归,当时就比较懵圈,还能有这种操作?看了看大神的代码:
class Solution {
public:
bool isPowerOfThree(int n) {
return(n>0&&int(log10(n)/log10(3))-log10(n)/log10(3)==0);
}
};
用对数来判断是否是3的倍数,int(log10(n)/log10(3))-log10(n)/log10(3)==0
这行代码实在是太机智了,自愧不如自愧不如......
-------------------------------------------
个性签名:一名会音乐、爱健身的不合格程序员
可以Follow博主的Github哦(っ•̀ω•́)っ✎⁾⁾