0
点赞
收藏
分享

微信扫一扫

五月训练 Day5

年夜雪 2022-05-05 阅读 87

文章目录

0. Leetcode 917. 仅仅反转字母

分析与解答

借用双指针的思想,要调换单词中所有字母的顺序,只需要首尾配对找到相应字母位置即可。因此令 i 从头开始,j 从尾开始寻找字母,找到后进行调换,直至 i >= j,表明已交换单词中的所有字母。

class Solution {
public:
    string reverseOnlyLetters(string s) {
        for (int i = 0, j = s.size() - 1; i < j;) {
            while (!(tolower(s[i]) >= 'a' && tolower(s[i]) <= 'z') && i < j) {
                i++;
            }

            while (!(tolower(s[j]) >= 'a' && tolower(s[j]) <= 'z') && i < j) {
                j--;
            }

            if (i >= j) {
                break;
            } else {
                char tmp = s[i];
                s[i] = s[j];
                s[j] = tmp;
            }

            // 交换完后将指针移到下一个待判断字符
            i++;
            j--;
        }

        return s;
    }
};

算法时间复杂度为 O ( N ) O(N) O(N)

1. Leetcode 167. 两数之和 II - 输入有序数组

分析与解答

解法1:二分查找
对于该问题,从头至尾遍历数组,对每个数 num,二分查找 target - num 在数组中是否存在。

class Solution {
public:
    int findPos(vector<int>& numbers, int low, int high, int target) {
        int l(low), r(high);
        while (l <= r) {
            int mid = l + ((r - l) >> 1);
            if (numbers[mid] < target) {
                l = mid + 1;
            } else if (numbers[mid] > target) {
                r = mid - 1;
            } else {
                return mid;
            }
        }
        
        return -1;
    }

    vector<int> twoSum(vector<int>& numbers, int target) {
        vector<int> result;
        bool find(false);
        for (int i = 0; i < numbers.size(); ++i) {
            int idx = findPos(numbers, i+1, numbers.size() - 1, target - numbers[i]);
            if (idx > 0) {
                result.push_back(i+1);
                result.push_back(idx+1);
                break;
            }
        }
        return result;
    }
};

算法时间复杂度为 O ( N l o g N ) O(NlogN) O(NlogN)
解法2:双指针
令两个指针分别指向首数字与尾数字,若两数和大于 target,则尾指针前移;若两数和大于 target,则首指针后移。

class Solution {
public:
    vector<int> twoSum(vector<int>& numbers, int target) {
        vector<int> result;
        int i(0), j(numbers.size() - 1);
        while (i < j) {
            if (numbers[i] + numbers[j] < target) {
                i++;
            } else if (numbers[i] + numbers[j] > target) {
                j--;
            } else {
                result.push_back(i + 1);
                result.push_back(j + 1);
                break;
            }
        }
        
        return result;
    }
};

算法时间复杂度为 O ( N ) O(N) O(N)

2. Leetcode 165. 比较版本号

分析与解答

令两个指针指向字符串头,后移指针 r,直至找到字符 .,此时从指针间取出字串,进行比较。重复这一过程直至遍历完成。

class Solution {
public:
    int compareVersion(string version1, string version2) {
        int l0(0), r0(0);
        int l1(0), r1(0);
        int result(0);
        
        version1 += ".";
        version2 += ".";
        while (r0 < version1.size() || r1 < version2.size()) {
            string str1 = "0";
            string str2 = "0";
            if (r0 < version1.size()) {
                while (version1[r0] != '.') {
                    r0++;
                }
                while (version1[l0] == '0') {
                    l0++;
                }
                if (r0 - l0 > 0) {
                    str1 = version1.substr(l0, r0 - l0);
                }
            }
            
            if (r1 < version2.size()) {
                while (version2[r1] != '.') {
                    r1++;
                }
                while (version2[l1] == '0') {
                    l1++;
                }
                if (r1 - l1 > 0) {
                    str2 = version2.substr(l1, r1 - l1);
                }
            }
            
            if (stoi(str1) < stoi(str2)) {
                result = -1;
                break;
            } else if (stoi(str1) > stoi(str2)) {
                result = 1;
                break;
            }
            
            r0++;
            l0 = r0;
            r1++;
            l1 = r1;
        }
        
        return result;
    }
};

算法时间复杂度为 O ( N ) O(N) O(N)

3. Leetcode 443. 压缩字符串

分析与解答

令指针 i 作为写指针,记录写字符的位置;指针 j 作为读指针,记录读取字符的位置,后移指针 j 直至新字符与前一字符不同,此时用指针 i 写入。重复该过程直至遍历完成。

class Solution {
public:
    int compress(vector<char>& chars) {
        int i(0), j(1);
        char preChar = chars[0];
        int count = 1;
        string cstr;
        while (j < chars.size()) {
            if (preChar != chars[j]) {
                chars[i++] = preChar;
                if (count > 1) {
                    cstr = to_string(count);
                    for (int k = 0; k < cstr.size(); ++k) {
                        chars[i++] = cstr[k];
                    }
                }
                preChar = chars[j];
                count = 1;
            } else {
                count++;
            }
            j++;
        }
        chars[i++] = preChar;
        if (count > 1) {
            cstr = to_string(count);
            for (int k = 0; k < cstr.size(); ++k) {
                chars[i++] = cstr[k];
            }
        }

        return i;
    }
};

算法时间复杂度为 O ( N ) O(N) O(N)

总结

用好双指针能够有效降低时间复杂度,简化问题。

举报

相关推荐

0 条评论