leetcode11-20

16 篇文章 0 订阅
12 篇文章 0 订阅

11.Container With Most Water
思路1:暴力搜索,每两个line计算一次area,选择最大的那个。但是超时。

 int maxArea(vector<int>& height) {
        int size = height.size();
        if (size < 2) return 0;
        int water = 0;
        int minLine = 0;
        int maxWater = 0;
        for (int i  = 0; i < size - 1; i++) {
            for (int j = i + 1; j < size; j++) {
                minLine = min(height[i],height[j]);
                water = (j - i) * minLine;
                if (water > maxWater) 
                    maxWater = water;
            }
        }
        return maxWater;
    }

思路2:既然暴力搜索不可以,那就想其他方法。我们知道每两个line之间,area大小取决于line之间的长度和其中小的那个line,就是木桶原理。所以当确定一个line,而且认为它在两个line中属于短的那个,所以我们计算area就是这个line的长度乘距离。所以首先选取第一个start和最后一个end比较,计算area,然后比较start和end哪个更短,说明和短的那条line做组合的line中,最大值就是start和end,然后哪边更短,在那边移动一步,重复上边的比较。可以看这个动图
每次从短的那条line向中间移动比较容易理解,但是有点难以理解的就是为什么是左右两条边比较,还有可能是中间一条line ,和经过的边进行比较。其实可以这么理解,如果已经比较完的边,说明这条边已经作为那个短板计算过了,我们记录的最长的宽度 * 短边,这时候我们就可以把它删除掉,然后再剩下的边中进行计算比较。

int maxArea(vector<int>& height) {
        int size = height.size();
        if (size < 2) return 0;
        int minLine = 0;
        int maxWater = 0;
        int water = 0;
        int i = 0,j = size - 1;
        while(i < j) {
            minLine = min(height[i],height[j]);
            water = (j - i) * minLine;
            if (water > maxWater)
                maxWater = water;
            if (minLine == height[i])
                i++;
            else 
                j--;
        }

        return maxWater;

    }

14 Longest Common Prefix 最长共同前缀
思路1:每两个一起比较,vector vec,先比较vec[0]和vec[1]的公共前缀,然后结果再和vec[2]比较,以此类推。

 string longestCommonPrefix(vector<string>& strs) {
        if (strs.empty()) return "";//注意这个空的情况
        string temp = strs[0];
        for (int i = 0; i < strs.size(); i++) {
            temp = commonPrefixOfTwo(temp,strs[i]);
            if (temp == "")
                return "";
        }
        return temp;
    }
    string commonPrefixOfTwo(string& s1,string& s2) {
        if (s1.empty() || s2.empty()) return "";
        string commonPre = "";
        for (int i = 0; i < s1.size(); i++) {
            if (s1[i] != s2[i] || s2.size() <= i) 
                return commonPre;
            commonPre.push_back(s1[i]);
        }
        return commonPre;
    }

思路2:纵向对比。我们定义两个变量i和j,其中i是遍历搜索字符串中的字符,j是遍历字符串集中的每个字符串。这里将单词上下排好,则相当于一个各行长度有可能不相等的二维数组,我们遍历顺序和一般的横向逐行遍历不同,而是采用纵向逐列遍历,在遍历的过程中,如果某一行没有了,说明其为最短的单词,因为共同前缀的长度不能长于最短单词,所以此时返回已经找出的共同前缀。我们每次取出第一个字符串的某一个位置的单词,然后遍历其他所有字符串的对应位置看是否相等,如果有不满足的直接返回res,如果都相同,则将当前字符存入结果,继续检查下一个位置的字符.

 //纵向比较
    string longestCommonPrefix(vector<string>& strs) {
        if (strs.empty()) return "";
        string temp = "";
        string flag = strs[0];
        for (int i = 0; i < flag.size(); i++) {
            char ch = flag[i];
            for (int j = 0; j < strs.size(); j++) {
                if (strs[j][i] != ch || strs[j].size() <= i)
                    return temp;
            }
            temp.push_back(ch);
        }
        return temp;
    }

15 3Sum
思路:因为a+b+c = 0,我们先把vector进行排序,然后从小到大进行遍历,把a 确定后,然后a后面的数进行加和判断是否等于-a,加和计算是取头和尾两个指针遍历计算。如果相等,那么就可以把结果放入vector,同时可以继续向中间移动指针,这时候要循环判断向中间靠近的数是否和之前的数相等。

vector<vector<int>> threeSum(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        vector<vector<int>> res;
        int size = nums.size();
        int oldKey = INT_MIN,newKey;
        for (int k= 0; k< size - 1; k++) {
            newKey = -nums[k];
            if (newKey == oldKey) {
                continue;
            }
            int i = k + 1;
            int j = size - 1;
            while(i < j) {
                if (nums[i] + nums[j] < newKey) 
                    i++;
                else if (nums[i] + nums[j] > newKey)
                    j--;
                else{
                    vector<int> temp;
                    temp.push_back(nums[k]);
                    temp.push_back(nums[i]);
                    temp.push_back(nums[j]);
                    res.push_back(temp);
                    while (nums[i+1] == nums[i] && i + 1 < size) i++;
                    while (nums[j-1] == nums[j] && j - 1 >= 0) j--;
                    i++;
                    j--;
                }
            }
            oldKey = newKey;

        }
        return res;
    }

16 3Sum Closest
思路:和15题思路相同

int threeSumClosest(vector<int>& nums, int target) {
        sort(nums.begin(),nums.end());
        int size = nums.size();
        int closetSum = INT_MAX;
        int closeTarget;

        for (int k = 0; k < size - 2; k++) {
            int i = k + 1;
            int j = size - 1;
            int key = target - nums[k];
            int diff;
            while (i < j) {
                if (nums[i] + nums[j] == key)
                    return target;
                else if (nums[i] + nums[j] < key) {
                    diff = key - (nums[i] + nums[j]);
                    if (diff < closetSum) {
                        closetSum = diff;
                        closeTarget = target - closetSum;
                    }

                    i++;
                }
                else {
                    diff = (nums[i] + nums[j]) - key;
                    if (diff < closetSum) {
                        closetSum = diff;
                        closeTarget = target + closetSum;
                    }
                    j--;
                }
            }
        }
        return closeTarget;
    }

17 Letter Combinations of a Phone Number

public:
    vector<string> letterCombinations(string digits) {
        vector<string> res;
        vector<string> nums = {"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};

        if (digits.size() == 0) {
            return res;
        }
        res.push_back("");
        for (char ch : digits) {
            int index = ch - '0';
            string numStr = nums[index];
            vector<string> temp;
            for (int i = 0; i < numStr.size(); i++) {
                for (int j = 0; j < res.size(); j++) {
                    temp.push_back(res[j] + numStr[i]);
                }
            }
            res = temp;
        }
        return res;
    }

18.4Sum
思路:和之前的2sum,3sum思路相同,只是多加了一层循环,核心思想就是先排序,然后两头指针,进行相加比较。为了防止有重复项,用了set。

vector<vector<int>> fourSum(vector<int>& nums, int target) {
        set<vector<int>> res;
        sort(nums.begin(),nums.end());
        int size = nums.size();
        for (int i = 0; i < size - 3; i++) {
            for (int j = i + 1; j < size - 2; j++) {
                int left = j + 1;
                int right = size - 1;
                int key = target - nums[i] - nums[j];
                int temp;
                while (left < right) {
                    temp = nums[left] + nums[right]; 
                    if (temp < key) {
                        left++;
                    }
                    else if (temp > key) {
                        right--;
                    }
                    else {
                        vector<int> vec = {nums[i],nums[j],nums[left],nums[right]};
                        res.insert(vec);
                        left++;
                        right--;
                    }
                }
            }
        }
        return vector<vector<int>>(res.begin(),res.end());
    }

19 Remove Nth Node From End of List
思路:既然要求一次遍历,就要在找到尾指针的时候,确定删除点的位置,所以选择双指针。首先cur指针先向前走N步,如果此时cur指向空,说明N为链表的长度,则需要移除的为首元素,那么此时我们返回head->next即可,如果cur存在,我们再继续往下走,此时pre指针也跟着走,直到cur为最后一个元素时停止,此时pre指向要移除元素的前一个元素,我们再修改指针跳过需要移除的元素即可。

ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* pre = head;
        ListNode* cur = head;
        if (!head) return NULL;
        int i = 0;
        while (i < n) {
            cur = cur->next;
            i++;
        }
        if (!cur) return head->next;
        while (cur->next) {
            pre = pre->next;
            cur = cur->next;
        }
        pre->next = pre->next->next;
        return head;
    }

20.Valid Parentheses
思路:这个就是入栈出栈。当遇到一个右括号时,判断栈顶元素是不是和它配对,我们查askii表,看到askii
括号之间差值是1或者2,所以判断差是不是小于3,就可以判断是不是配对。

 bool isValid(string s) {
       stack<char> brackets;
        for (char ch : s) {
            if (ch == '(' || ch == '{' || ch == '[') {
                brackets.push(ch);
            }
            else {
                if (brackets.empty()) return false;
                char temp = brackets.top();;
                if (abs(ch - temp) < 3)
                    brackets.pop();
                else
                    return false;
            }
        }
        return brackets.empty();
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值