编程日记,尽量保证每天至少3道leetcode题,仅此记录学习的一些题目答案与思路,尽量用多种思路来分析解决问题,不足之处还望指出。标红题为之后还需要再看的题目。
今日题目:1、二进制加法;2、查找子串;3、数组区域加法;4、计算素数个数;5、找两数之和。
67. Add Binary | Difficulty: Easy
Given two binary strings, return their sum (also a binary string).
For example,
a = “11”
b = “1”
Return “100”.
题意:给两个二进制数的字符串,求它们的和的字符串形式
思路:
1、从最低位开始遍历两个字符串即可。注意进位。
代码:
C++
class Solution {
public:
string addBinary(string a, string b) {
string res = "";
int i = a.size()-1,j = b.size()-1,c = 0;
//i,j代表a、b的最低位,循环结束的条件是i、j全部小于0并且进位c等于0,每一次加法注意进位就行
while(i>=0 || j>=0 || c==1)
{
c+=i>=0?a[i--]-'0':0;
c+=j>=0?b[j--]-'0':0;
res = char(c%2 + '0') + res;
c /=2;
}
return res;
}
};
结果:4ms
28. Implement strStr() | Difficulty: Easy
Implement strStr().
Returns the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.
题意:找到字符串的子串位置,找不到就返回-2
思路:
1、
代码:
C++
class Solution {
public:
int strStr(string haystack, string needle) {
if(needle.length()==0) return 0;
int length = haystack.length();
int sublength = needle.size();
int i=0;
for(i;i<length-sublength+1;i++)
{
int j = 0;
for(;j<sublength;j++)
{
if(haystack[i+j]!=needle[j]) break;
}
if(j==sublength) return i;
}
return -1;
}
};
结果:4ms
2、python的字符串直接有find方法可以用,但是这题显然不是这样的考察点。
python
class Solution(object):
def strStr(self, haystack, needle):
"""
:type haystack: str
:type needle: str
:rtype: int
"""
return haystack.find(needle)
结果:40ms
303. Range Sum Query - Immutable | Difficulty: Easy
Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive.
Example:
Given nums = [-2, 0, 3, -5, 2, -1]
sumRange(0, 2) -> 1
sumRange(2, 5) -> -1
sumRange(0, 5) -> -3
Note:
1.You may assume that the array does not change.
2.There are many calls to sumRange function.
题意:整型数组区域加法
思路:
1、额外创一个累加数组,然后返回前j个数的累加-前i-1个数的累加(因为i到j之前的和包含了第i个元素,做减法的时候就不应该包含第i个元素)。
class NumArray {
public:
NumArray(vector<int> &nums) {
accs.push_back(0);
for(int i=0;i<nums.size();i++)
{
accs.push_back(accs.back()+nums[i]);
}
//这个地方可以不移除开始加的0,不过那样后面所有的坐标都要加1,这里为了保证坐标和之前的相同把它移除了
accs.erase(accs.begin());
}
int sumRange(int i, int j) {
return accs[j]-accs[i-1];
}
private:
vector<int> accs;
};
// Your NumArray object will be instantiated and called as such:
// NumArray numArray(nums);
// numArray.sumRange(0, 1);
// numArray.sumRange(1, 2);
结果:28ms
204. Count Primes | Difficulty: Easy
Description:
Count the number of prime numbers less than a non-negative number, n.
题意:找到小于非负整数n的所有质数的个数
思路:
1、很经典的题目。首先需要知道怎么去判断一个数是否是质数。
质数的定义是什么?除了1和它本身以外不再有其他的除数整除。我们需要判断n是否是质数的时候应该怎么做?那么很自然的一个想法就是从2-n-1遍历一次,找是否能整除,判断是否质数。但是这里面有些多于,因为一个数如果要是质数,那么分解之后的两个数相差最大的时候是2*n/2 = n,那么很显然,如果在2-n/2-1之间还没找到能整除n的数,那么在n/2-n-1之间也一定不会找到能整除n的数。
这样就将n次查找变为n/2。但是真的有必要找完2-n/2-1之间的所有数字吗?并不需要,举个栗子:
我们要判断12是否质数,按照之前所说,只需找2-5之间是否都不能整除12,如果满足就是。
对12做因式分解
2 × 6 = 12
3 × 4 = 12
4 × 3 = 12
6 × 2 = 12
这里具有对称性,即在2-根号n之间能找到的整除的数,在根号n到n-1一定能找到一组对称的数,那么问题就可以从2到n/2-1之间遍历变成2到根号n之间。在n很小的时候体现不出,n增大的时候可以减少很多次判断。
这样先写出判断质数的方法,然后再遍历一次逐次判断,复杂度N的1.5次方。
代码很好读,但是却出现了 Time Limit Exceeded错误,也就是说在数字很大的时候复杂度还是太高了。
代码:
C++
class Solution {
public:
bool isPrimes(int n)
{
if(n==2) return true;
for(int i=2;i<=sqrt(n);i++)
{
if(n%i==0) return false;
}
return true;
}
int countPrimes(int n) {
int count = 0;
for(int i=2;i<n;i++)
{
if(isPrimes(i)) count++;
}
return count;
}
};
结果: Time Limit Exceeded
2、wiki中埃拉托斯特尼筛法是一种计算一定范围内所有素数的方法,所使用的原理是从2开始,将每个素数的各个倍数,标记成合数。一个素数的各个倍数,是一个差为此素数本身的等差数列。此为这个筛法和试除法不同的关键之处,后者是以素数来测试每个待测数能否被整除。
class Solution {
public:
int countPrimes(int n) {
int count = 0;
bool Primes[n];
//首先初始化一个标记数组
for(int i=2;i<n;i++)
Primes[i]=true;
//对于2到根号n之间的所有数i,如果已经是false了,说明不是质数,那么它的倍数也同样不是质数。每次将i的倍数都标记为false。
for(int i=2;i*i<n;i++)
{
if(!Primes[i]) continue;
for(int j=i*i;j<n;j+=i)
Primes[j]=false;
}
//直到最后还剩下true的个数就是质数的个数,所有的合数都会被标记为false
for(int i=2;i<n;i++)
{
if(Primes[i]) count++;
}
return count;
}
};
结果:56ms
1. Two Sum | Difficulty: Easy
Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution.
Example:
Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].
题意:找到数组的两个值,使得其和为target,返回下标的值。
思路:
1、首先记录下原有数组的序号信息,用python的tuple结构,然后根据value进行排序。排序好之后一头一尾向中间靠拢,判断两个值之和与target之间的关系。
代码:
python
class Solution(object):
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
res = []
nums = [(idx,e)for idx,e in enumerate(nums)]
new = sorted(nums,key = lambda x:x[1])
i = 0
j = len(new)-1
while i!=j:
if new[i][1]+new[j][1]>target:
j-=1
elif new[i][1]+new[j][1]<target:
i+=1
else:
res.append(new[i][0])
res.append(new[j][0])
break
if len(res):
return res
else:
return None
结果:48ms
2、利用一个C++的map,对每个数计算target-num,就是还要找的那个数,如果在map中存在,就返回那个数的位置,如果不存在,就将当前的数也加入map中去。举个栗子:
[3,2,4] 和为6
i=0 num = 3 rest = 6-3=3 ,map中没有3,将3作为key加入map,value为0
i=1 num = 2 rest = 6-2 = 4,map中没有4,将4作为key加入map,value为1
i =2 num=4,rest = 6-4=2,map中有2,找到,返回2的value1,1,2就是所求结果。
C++
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> res;
unordered_map<int,int> hash;
for(int i=0;i<nums.size();i++)
{
int rest = target-nums[i];
if(hash.find(rest)!=hash.end())
{
res.push_back(hash[rest]);
res.push_back(i);
}
hash[nums[i]] = i;
}
return res;
}
};