leetcode第一周解题总结(1,28,125,151,167)

本周一共完成五题,知识点array/string,创建一个list存放已完成的题目。
list

1. Two Sum

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, and you may not use the same element twice.
Example:
Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].

题意解析:

  • 寻找数组中两个和为特定目标的数字的下标。
  • 唯一解,一个元素只能使用一次。

解题思路:

首先想到的就是两重循环去遍历数组中的所有元素相加的结果,算法复杂度为O(n^2)。

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        size_t len = nums.size();
        for(size_t i = 0; i < len - 1 ; i++) {
            for(size_t j = i + 1; j < len; j++) {
                if(nums[i] + nums[j] == target) {
                    vector<int> a(2);
                    a[0]=i;
                    a[1]=j;
                    return a;
                }
            }
        }
    }
};

result
在一些相关资料中显示,使用这种方法写的c语言版本代码会出现超时的情况,该代码虽然通过但依然使用了远高于平均水平的时间。
因此,需要对算法进行优化,使用哈希表的思想,通过一次遍历将原始数组的元素保存到数值对应的下标中,存放的内容为原始下标加一,0代表该数值不存在。因为存在负数,所以使用了两个vector,分别代表正数和负数。而因为只有唯一解,可以得知,一个数字只可能重复两次,最初使用下标相加的方法,存储两个下标,代码通过,但是运行时间依然较长。
之后阅读了标准答案改为以下版本,在遍历进行哈希时就进行查找,这样就避免了存放重复元素和进一步的判断。

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        size_t len = nums.size();
        vector<int> a(30000);
        vector<int> b(30000);
        vector<int> result(2);
        for(size_t i = 0; i < len ; i++) {
            int y = nums[i];
            if (target - y >= 0 && a[target - y] >= 1) {
                result[0] = a[target - y] - 1;
                result[1] = i;
                return result;
            }
            if (target - y < 0 && b[y - target] >= 1) {
                result[0] = b[y - target] - 1;
                result[1] = i;
                return result;
            }
            if(nums[i] >= 0) {
                a[nums[i]] += i + 1;
            } else {
                b[-nums[i]] += i + 1;
            }
        }  
    }
};

这里写图片描述

这种方法的算法复杂度为O(n),通过哈希建立映射关系从而加快了查找的速度。


167. Two Sum II - Input array is sorted

Given an array of integers that is already sorted in ascending order,
find two numbers such that they add up to a specific target number.
The function twoSum should return indices of the two numbers such that
they add up to the target, where index1 must be less than index2.
Please note that your returned answers (both index1 and index2) are
not zero-based.
You may assume that each input would have exactly one solution and you
may not use the same element twice.
Input: numbers={2, 7, 11, 15}, target=9
Output: index1=1, index2=2

题意解析:

与上一题基本相同,不同在于数组已经排序,返回下标从1开始。

解题思路:

  • 二分查找
    因为数组已经排好序,容易联想到二分查找,第一种方法遍历一遍数组,再进行二分查找,算法复杂度为O(nlogn)。
class Solution {
public:
    vector<int> twoSum(vector<int>& numbers, int target) {
        vector<int> result(2);
        size_t len = numbers.size();
        for (size_t i = 0; i < len - 1; i++) {
            if (numbers[i] + numbers[len - 1] < target) 
                continue;

            int temp = target - numbers[i];
            int left = i + 1;
            int right = len - 1;
            int mid = (i + len)/2;
            while (left < right && numbers[mid]!= temp) {
                if (temp < numbers[mid]) {
                    right = mid - 1;
                } else {
                    left = mid + 1;
                }
                mid = (left + right) / 2;
            }
            if (temp == numbers[mid]) {
                result[0] = i + 1;
                result[1] = mid + 1;
                return result;
            }
        }
    }
};
  • 两个指针

    第二种方法使用两个指针,分别指向数组的头部和尾部。如果当前指向的两个数字之和小于target,那么头部指针向前移动一位;如果当前两个数字之和大于target,那么尾部指针向后移动一位,最终到达结果。算法复杂度为O(n)。

class Solution {
public:
    vector<int> twoSum(vector<int>& numbers, int target) {
        vector<int> result(2);
        size_t len = numbers.size();
        int left = 0; 
        int right = len - 1;
        while(1) {
            int sum = numbers[left] + numbers[right];
            if (sum == target) {
                result[0] = left + 1;
                result[1] = right + 1;
                return result;
            }

            if (sum < target) {
                left ++;
            }
            if (sum > target) {
                right --;
            }
        }
    }
};

125. Valid Palindrome

Given a string, determine if it is a palindrome, considering only
alphanumeric characters and ignoring cases.
For example, “A man, a plan, a canal: Panama” is a palindrome. “race a
car” is not a palindrome.

题意解析: 判断是否为回文串

解题思路: 与上一题两个指针的思想类似,当遇到非字母数字的字符则指针移动一位,当指向的两个元素都为字母或者数字则进行比较,如果相等则两个指针都移动一位,如果不相等则不是回文串,算法复杂度O(n)。

class Solution {
public:
    bool isPalindrome(string s) {
        int len = s.size();
        int left = 0;
        int right = len - 1;

        while (left <= right) {
            if (!isalnum(s[left])) {
                left ++;
                continue;
            }
            if (!isalnum(s[right])) {
                right --;
                continue;
            }

            if (isalnum(s[left]) && isalnum(s[right])) {
                if (tolower(s[left]) == tolower(s[right])) {
                    left ++;
                    right --;
                } else {
                    return false;
                }
            }
        }
        return true;
    }
};

28. Implement strStr()

Implement strStr().

Returns the index of the first occurrence of needle in haystack, or -1
if needle is not part of haystack.

题意解析: 题目写的很玄,其实就是返回字串首次出现的下标。

解题思路: 直接使用两重循环进行搜索,算法复杂度O(mn)。

class Solution {
public:
    int strStr(string haystack, string needle) {
        int len1 = haystack.size();
        int len2 = needle.size();
        if (len2 == 0) return 0;
        if (len1 < len2) return -1;
        if (len1 == len2) {
            if(haystack == needle) return 0;
            return -1;
        }

        for (size_t i = 0; i <= len1 - len2; i++) {
            for(size_t j = 0; j < len2; j++) {
                if (needle[j] != haystack[i+j]) break;
                if (j == len2 - 1) return i;
            }
        }
        return -1;
    }
};

答案中的Rabin-Karp algorithm, KMP algorithm, Boyer-Moore algorithm.有待研究。

151. Reverse Words in a String

Given an input string, reverse the string word by word.

For example, Given s = “the sky is blue”, return “blue is sky the”.

Update (2015-02-12): For C programmers: Try to solve it in-place in
O(1) space.

题意解析: 反转字符串中的单词顺序。

解题思路: 首先记录下字符串中所有的单词,再按照倒序重新拼接。

class Solution {
public:
    void reverseWords(string &s) {
    size_t len = s.size();
    int counter = 0;
    vector<string> result;
    for (size_t i = 0; i <= len; i++) {
        if (s[i] == ' ' && s[i - 1] == ' ') continue;

        if (s[i] == ' ' || i == len) {
            if (counter > 0) {
                string a;
                for (int j = 0; j < counter; j ++) {
                    a.push_back(s[i - counter + j]);
                }
                result.push_back(a);
                counter = 0;
            }
        } else {
            counter++;
        }
    }
    s = "";
    if (result.size() > 0) {
        for (int x = result.size() - 1; x >= 0; x--) {
            if (x != 0) {
                s += result[x] + ' ';
            } else {
                s += result[x];
            }
        }
    }
}
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值