这四题有两题困难的,看起来有点硬核,但是问题不大。这最后四题做完要休息一段时间再做了,最近有点忙,很难受。
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)) &÷nd - (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;
}
来源:CSDN
作者:Magic_Conch_Shell
链接:https://blog.csdn.net/weixin_43813453/article/details/103481622