leetcode题解日练--2016.6.29

编程日记,尽量保证每天至少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;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值