1. 把数组排成最小的数
输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。
分析:之前做过这道题,这次做的第一个想法和之前一样,首先要将数字转成字符串,然后比较字符串的大小,而且比较的结果应该是“321”<“32” && "32"<"3"
,或许我们可以这样考虑“32”==“322” && "3"=="33"
。所以需要这样判断,当比较 “321” 与 “32” 时,他们的前两个字符相等,而 “321” 的第三个字符小于 “32” 的第二个字符,于是我们得出 “321”<“32”
的结论。想法看起来十分复杂又难实现。
今天在纸上写下“32132<32321”
的时候,突然脑袋开窍。我们可以通过判断 str1+str2
与 str2+str1
的关系得到两字符串的大小啊!于是编程如下:
class Solution {
public:
static bool strcmp(const string& str1, const string& str2)
{//这里一定要是静态函数,因为静态函数指针等同于函数指针,
//而非静态函数指针比普通函数指针多了一个类名。
if(str1+str2<str2+str1) //str1<str2,升序排序
return true;
else return false;
}
string PrintMinNumber(vector<int> numbers) {
vector<string> vecstr;
int size = numbers.size(), i;
for(i=0; i<size; ++i)
vecstr.push_back(to_string(numbers[i]));
sort(vecstr.begin(),vecstr.end(),strcmp);
string ret;
for(i=0; i<size; ++i)
ret += vecstr[i];
return ret;
}
};
2. 丑数.
把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
分析:最小的丑数是 1,并且除了 1 之外的所有丑数都是由其他丑数 *2 或 *3 或 *5 得到的。设置一个丑数序列 ugly,每次找到一个稍大的丑数就放进队列,再设置三个指针 pos2、pos3、pos5,分别指向 2、3、5 三个数想要乘的丑数。下一个添加进队列的丑数是 ugly[pos2]*2、ugly[pos3]*3、ugly[pos3]*3 的最小值。如果新得到的丑数是由 2 乘之前某个丑数得到的,就把 pos2 指针移向下一位。
class Solution {
public:
int GetUglyNumber_Solution(int index) {
if(index<=0) return 0;
vector<int> ugly(index);
ugly[0]=1;
int pos2=0, pos3=0, pos5=0;
for(int i=1; i<index; ++i)
{
ugly[i] = min(min(ugly[pos2]*2, ugly[pos3]*3), ugly[pos5]*5);
if(ugly[pos2]*2 == ugly[i]) ++pos2;
if(ugly[pos3]*3 == ugly[i]) ++pos3;
if(ugly[pos5]*5 == ugly[i]) ++pos5;
}
return ugly[index-1];
}
};
3. 第一个只出现1次的字符
在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写).(从0开始计数)
分析:奇怪的事情发生了——在牛客的编辑器上提示 unordered_map 是未声明的 identifier,但是仍然能通过百分百的用例。
ps:本以为这道题有什么神奇的解法呢。
class Solution {
public:
int FirstNotRepeatingChar(string str) {
unordered_map<char, int> cnt;
for(int i=0; i<str.length(); ++i)
++cnt[str[i]];
for(int i=0; i<str.length(); ++i)
if(cnt[str[i]]==1)
return i;
return -1;
}
};
4. 数组中的逆序对.
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数 P 。并将 P 对 1000000007 取模的结果输出。 即输出P % 1000000007。题目保证输入的数组中没有的相同的数字,数据范围:
对于%50的数据,size<=10^4
对于%75的数据,size<=10^5
对于%100的数据,size<=2*10^5
分析:归并排序的应用
class Solution {
public:
int mod = 1000000007;
void merge(vector<int>& data, vector<int>& tmp, int l, int mid, int r, int &ret)
{
int t=0, i=l, j=mid+1;
while(i<=mid && j<=r)
{
if(data[i]>data[j])
{
tmp[t++] = data[j++];
ret += (mid-i+1);
ret %= mod;
}else{
tmp[t++] = data[i++];
}
}
while(i<=mid)
tmp[t++] = data[i++];
while(j<=r)
tmp[t++] = data[j++];
for(i=0; i<=r-l; ++i)
data[l+i] = tmp[i];
}
void split_merge(vector<int>& data, vector<int>& tmp, int l, int r, int& ret)
{
if(l>=r) return;
int mid = l+((r-l)>>1);
split_merge(data, tmp, l, mid, ret);
split_merge(data, tmp, mid+1, r, ret);
merge(data, tmp, l, mid, r, ret);
}
int InversePairs(vector<int> data) {
int size = data.size(), ret=0;
vector<int> tmp(size);
split_merge(data, tmp, 0, size-1, ret);
return ret;
}
};