题目一:
输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。
输出描述: 对应每个测试案例,输出两个数,小的先输出。
解题思路:
数列满足递增,设两个头尾两个指针i和j,
若ai + aj == sum,就是答案(相差越远乘积越小)
若ai + aj > sum,aj肯定不是答案之一(前面已得出 i 前面的数已是不可能),j -= 1
若ai + aj < sum,ai肯定不是答案之一(前面已得出 j 后面的数已是不可能),i += 1
时间复杂度O(n)
class Solution {
public:
vector<int> FindNumbersWithSum(vector<int> array,int sum) {
int i=0,j=array.size()-1;
vector<int> res;
while(i<j)
{
if(array[i]+array[j]==sum)
{
res.push_back(array[i]);
res.push_back(array[j]);
break;
}
else if(array[i]+array[j]<sum)
i++;
else
j--;
}
return res;
}
};
题目二:
汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”。是不是很简单?OK,搞定它!
解法很多;
方案一:
class Solution {
public:
string LeftRotateString(string str, int n) {
if(str.size()==0) return str;
int rn=n%str.size();
str.insert(str.end(),str.begin(),str.begin()+rn);
str.erase(str.begin(),str.begin()+rn);
return str;
}
};
方案二:
class Solution {
public:
string LeftRotateString(string str, int n) {
int len = str.length();
if(len == 0) return str;
n = n % len;
str += str;
return str.substr(n, len);
}
};
方案三:
假设字符串abcdef,n=3,设X=abc,Y=def,所以字符串可以表示成XY,如题干,问如何求得YX。假设X的翻转为XT,XT=cba,同理YT=fed,那么YX=(XTYT)T,三次翻转后可得结果。
class Solution {
public:
string LeftRotateString(string str, int n)
{
int len = str.size();
if(len == 0) return str;
n %= len;
for(int i = 0, j = n - 1; i < j; ++i, --j) swap(str[i], str[j]);
for(int i = n, j = len - 1; i < j; ++i, --j) swap(str[i], str[j]);
for(int i = 0, j = len - 1; i < j; ++i, --j) swap(str[i], str[j]);
return str;
}
};
方案四:
class Solution {
public:
void fun(string &s,int start,int end)
{
char temp;
while(start<end)
{
temp=s[start];
s[start]=s[end];
s[end]=temp;
start++;
end--;
}
}
string LeftRotateString(string str, int n) {
int len=str.length();
if(0==len || 0==n)
return str;
string &temp=str;
fun(temp,0,n-1);
fun(temp,n,len-1);
fun(temp,0,len-1);
return str;
}
};
方案五:
class Solution {
public:
string LeftRotateString(string str, int n) {
int len = str.length();
if(len == 0) return str;
n = n % len;
reverse(str.begin(),str.begin()+n);
reverse(str.begin()+n,str.end());
reverse(str.begin(),str.end());
return str;
}
};
题目三:
牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上。同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思。例如,“student. a am I”。后来才意识到,这家伙原来把句子单词的顺序翻转了,正确的句子应该是“I am a student.”。Cat对一一的翻转这些单词顺序可不在行,你能帮助他么?
三种解法:
方案一:
class Solution {
public:
string ReverseSentence(string str) {
auto first=str.begin();
auto second=str.begin();
for(;second!=str.end();second++)
{
if(*second==' ')
{
reverse(first,second);
first=second+1;
}
}
reverse(first,second);
reverse(str.begin(),str.end());
return str;
}
};
方案二:
class Solution {
public:
void ReverseWord(string &str, int s, int e)
{
while(s < e)
swap(str[s++], str[e--]);
}
string ReverseSentence(string str) {
ReverseWord(str, 0, str.size() - 1); //先整体翻转
int s = 0, e = 0;
int i = 0;
while(i < str.size())
{
while(i < str.size() && str[i] == ' ') //空格跳过
i++;
e = s = i; //记录单词的第一个字符的位置
while(i < str.size() && str[i] != ' ') //不是空格 找单词最后一个字符的位置
{
i++;
e++;
}
ReverseWord(str, s, e - 1); //局部翻转
}
return str;
}
};
方案三:
class Solution {
public:
string ReverseSentence(string str) {
string res = "", tmp = "";
for(unsigned int i = 0; i < str.size(); ++i){
if(str[i] == ' ') res = " " + tmp + res, tmp = "";
else tmp += str[i];
}
if(tmp.size()) res = tmp + res;
return res;
}
};
题目四:
LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张^_^)...他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决定去买体育彩票,嘿嘿!!“红心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是顺子.....LL不高兴了,他想了想,决定大\小 王可以看成任何数字,并且A看作1,J为11,Q为12,K为13。上面的5张牌就可以变成“1,2,3,4,5”(大小王分别看作2和4),“So Lucky!”。LL决定去买体育彩票啦。 现在,要求你使用这幅牌模拟上面的过程,然后告诉我们LL的运气如何, 如果牌能组成顺子就输出true,否则就输出false。为了方便起见,你可以认为大小王是0。
方案一:
1、排序
2、计算所有相邻数字间隔总数
3、计算0的个数
4、如果第2、3步相等,就是顺子
5、如果出现对子,则不是顺子
class Solution {
public:
bool IsContinuous( vector<int> numbers ) {
if(numbers.size()!=5) return false;
sort(numbers.begin(),numbers.end());
int C0=count(numbers.begin(),numbers.end(),0);
for(int i=C0+1;i<numbers.size();i++)
{
if(numbers[i]==numbers[i-1]) return false;
else
{
if(numbers[i]-numbers[i-1]-1>C0) return false;
else
C0-=numbers[i]-numbers[i-1]-1;
}
}
return true;
}
};
class Solution {
public:
bool IsContinuous( vector<int> numbers ) {
if(numbers.size()!=5) return false;
int numOfZero = 0;
int numOfInterval = 0;
sort(numbers.begin(),numbers.end());
for(int i=0;i<numbers.size()-1;i++)
{
// 计算癞子数量
if (numbers[i] == 0) {
numOfZero++;
continue;
}
// 对子,直接返回
if (numbers[i] == numbers[i + 1])
return false;
numOfInterval += numbers[i + 1] - numbers[i] - 1;
}
if (numOfZero >= numOfInterval) {
return true;
}
return false;
}
};
方案二:
max 记录 最大值
min 记录 最小值
满足条件 1 max - min <5
2 除0外没有重复的数字(牌)
3 数组长度 为5
class Solution {
public:
bool IsContinuous( vector<int> numbers ) {
if(numbers.size()!=5) return false;
int* dp=new int[14];
int max=-1;
int min=14;
for(int i=0;i<numbers.size();i++)
{
if(numbers[i]==0) continue;
dp[numbers[i]]++;
if(dp[numbers[i]]>1) return false;
if(numbers[i] >max)
max = numbers[i];
if(numbers[i] <min)
min = numbers[i];
}
if(max-min>=5) return false;
return true;
}
};
参考:https://www.nowcoder.com/profile/3765387/codeBookDetail?submissionId=18859853