LeetCode刷题记录贴29~32

断了今生、忘了曾经 提交于 2019-12-11 00:38:57

这四题有两题困难的,看起来有点硬核,但是问题不大。这最后四题做完要休息一段时间再做了,最近有点忙,很难受。
29.两数相除
不能用乘法除法,mod,那岂不是只能用减法了,那么我们的任务就是用减法去优化这个过程。
现在喜欢做什么都用递归去写,虽然用递归效率很低,但是写起来帅气,而且可读性要稍微高那么一点。
我服了,下面的代码明明把所有的值都变成负的然后传进递归,但是还是报错我溢出了,莫名其妙卡了好久。。。

int divide(int dividend, int divisor, int index, int currentAns, int currentIndex) {
    if (dividend > divisor)
        return currentIndex;
    if (dividend - (currentAns + currentAns) <= 0)
        return divide(dividend - currentAns - currentAns, divisor, index + index, currentAns + currentAns, currentIndex + index + index);
    else if (dividend - currentAns <= 0)
        return divide(dividend - currentAns, divisor, index, currentAns, currentIndex + index);
    else
        return divide(dividend, divisor, -((-index)>>1), -((-currentAns)>>1), currentIndex);
}
int divide(int dividend, int divisor) {
    if (dividend == INT_MIN && divisor == -1)
        return INT_MAX;
    if (dividend > 0 && divisor < 0)
        return -divide(-dividend, divisor, 1, divisor, 0);
    else if (dividend < 0 && divisor < 0)
        return divide(dividend, divisor, 1, divisor, 0);
    else if (dividend > 0 && divisor > 0)
        return divide(-dividend, -divisor, 1, -divisor, 0);
    else
        return -divide(dividend, -divisor, 1, -divisor, 0);
}

终于理解了,这是因为currentAns+currentAns可能会溢出。。

int divide(int dividend, int divisor, int index, int currentAns, int currentIndex) {
    if (dividend > divisor)
        return currentIndex;
    if ((currentAns>-(INT_MAX>>1)) &&dividend - (currentAns + currentAns) <= 0)
        return divide(dividend - currentAns - currentAns, divisor, index + index, currentAns + currentAns, currentIndex + index + index);
    else if (dividend - currentAns <= 0)
        return divide(dividend - currentAns, divisor, index, currentAns, currentIndex + index);
    else
        return divide(dividend, divisor, -((-index)>>1), -((-currentAns)>>1), currentIndex);
}
int divide(int dividend, int divisor) {
    if (dividend == INT_MIN && divisor == -1)
        return INT_MAX;
    else if (dividend == INT_MIN && divisor == 1)
        return INT_MIN;
    if (dividend > 0 && divisor < 0)
        return -divide(-dividend, divisor, 1, divisor, 0);
    else if (dividend < 0 && divisor < 0)
        return divide(dividend, divisor, 1, divisor, 0);
    else if (dividend > 0 && divisor > 0)
        return divide(-dividend, -divisor, 1, -divisor, 0);
    else
        return -divide(dividend, -divisor, 1, -divisor, 0);
}

围观了一下题解的代码,好多都不符合要求,用了其他的数据类型,不过讲道理,我这个移位操作也算除法,不过可以通过在参数里面加上两个值来避免使用除法。
30.串联所有单词的字串
虽然是个hard题目,但是我看到它觉得思路十分清晰,因为单词的长度是固定的,所以很容易能提取出字串,用map肯定是能解决的,但是效率什么的就不知道了,最差的情况可能就是输入的全部是一个字母。

vector<int> findSubstring(string s, vector<string>& words) {
    map<string, int> mp, mp1;
    vector <int> ans;
    if (s.length() == 0||words.size()==0)
        return ans;
    int len1 = words.size(), j, index, len2 = s.length(),len3 = words[0].size();
    string subStr;
    for (int i = 0; i < len1; i++)
        mp[words[i]]++;
    for (int i = 0; i <= len2 - len3 * len1; i++)
    {
        if (mp[s.substr(i, len3)] == 0)
            continue;
        j = i;
        index = 0;
        mp1.clear();
        mp1 = mp;
        while (j <= len2 - len3)
        {
            subStr = s.substr(j, len3);
            if (mp1[subStr] == 0)
                break;
            else
            {
                mp1[subStr]--;
                index++;
                j += len3;
            }
            if (index == len1)
            {
                ans.push_back(i);
                break;
            }
        }
    }
    return ans;
}

在这里插入图片描述
效率还过得去吧。。。我这个思路居然叫滑动窗口,有意思,但是效率可以进一步优化,比如在上面加入部分剪枝再提交:

vector<int> findSubstring(string s, vector<string>& words) {
       map<string, int> mp, mp1;
       vector <int> ans;
       if (s.length() == 0 || words.size() == 0)
              return ans;
       int len1 = words.size(), j, index, len2 = s.length(), len3 =  words[0].size(),cutoff=0,cutoff1;
       string subStr;
       for (int i = 0; i < len1; i++)
       {
              cutoff += words[i][0];
              mp[words[i]]++;
       }
       for (int i = 0; i <= len2 - len3 * len1; i++)
       {
              cutoff1 = 0;
              for (int k = 0; k < len1; k++)
                     cutoff1 += s[i + k * len3];
              if (cutoff1 != cutoff)
                     continue;
              if (mp[s.substr(i, len3)] == 0)
                     continue;
              j = i;
              index = 0;
              mp1.clear();
              mp1 = mp;
              while (j <= len2 - len3)
              {
                     subStr = s.substr(j, len3);
                     if (mp1[subStr] == 0)
                           break;
                     else
                     {
                           mp1[subStr]--;
                           index++;
                           j += len3;
                     }
                     if (index == len1)
                     {
                           ans.push_back(i);
                           break;
                     }
              }
       }
       return ans;
}

在这里插入图片描述
看,是不是很优秀~
31.下一个排列
题目需要原地修改,肯定是有某种技巧的,在纸上画一下,然后找找看吧。。
找到一个思路,从后面往前面看,找到第一个后面大于前面的序列,然后把后面第一个大于那个数的数和那个交换,然后其他部分重新排序,看起来好像是对的。。。
比如1432,4>1那么把432中大于1的最小的数2和1交换,2后面重新排序,就变成了2134.
速度打败95%的人,还行。。

void nextPermutation(vector<int>& nums) {
    int j;
    for (int i = nums.size()-1; i > 0; i--)
    {
        if (nums[i] > nums[i - 1])
        {
            for (j = i + 1; j < nums.size(); j++)
                if (nums[j] <= nums[i - 1])
                    break;
            swap(nums[j-1], nums[i - 1]);
            sort(nums.begin() + i,nums.end());
            return;
        }
    }
    sort(nums.begin(), nums.end());
}

32.最长有效括号
一个dp解决

int longestValidParentheses(string s)
{
    vector <int> v;
    string s1 = " ";
    s1 += s;
    s = s1;
    v.push_back(0);
    int maxnum=0;
    for (int i = 1; i < s.length(); i++)
    {
        if (s[i] == '(')
            v.push_back(0);
        else if (s[i] == ')'&&s[i - 1] == '(')
            v.push_back(v[i - 2] + 2);
        else if (s[i] == ')' && s[i - 1] == ')'&& s[i-1-v[i-1]] == '(')
            v.push_back(v[i - 1] + 2 + v[i - 1 - v[i - 1]-1]);
        else
            v.push_back(0);
        maxnum = max(maxnum,v[v.size()-1]);
    }
    return maxnum;
}

用栈的方法,这个想不到,看题解的,还是挺巧妙的

int longestValidParentheses(string s)
{
    stack <int > st;
    int maxnum = 0;
    st.push(-1);
    for (int i = 0; i < s.length(); i++)
    {
        if (s[i] == '(')
            st.push(i);
        else
        {
            st.pop();
            if (st.size() == 0)
                st.push(i);
            else
                maxnum = max(maxnum,i-st.top());
        }
    }
    return maxnum;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!