31整数中1出现的次数(从1到n整数中1出现的次数)
求出1 ~ 13的整数中1出现的次数,并算出100~ 1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。
class Solution {
public:
int NumberOf1Between1AndN_Solution(int n){
if(n < 1) return 0;
if(n < 9) return 1;
int high = 0;
int k = 0;
int cur = 0;
int count = 0;
for(int i = 1; k = n / i; i *= 10){
high = k / 10;
count += high * i;
cur = k % 10;
if(cur > 1)
count += i;
else if(cur == 1)
count += n - k * i + 1;
}
return count;
}
};
32把数组排成最小的数
输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。
class Solution {
public:
static bool cmp(string x,string y){
int xl=x.size();
int yl=y.size();
int i;
for(i=0 ; i<xl && i<yl ; i++){
if(x[i]<y[i])return true;
if(x[i]>y[i])return false;
}
if(i==xl && i<yl){
return y[i]>=x[0];
}
if(i==yl && i<xl){
return x[i]<=x[0];
}
return true;
}
string PrintMinNumber(vector<int> numbers) {
vector<string> s;
for(int i=0;i<numbers.size();i++){
stringstream ss;
ss<<numbers[i];
string tmp;
ss>>tmp;
s.push_back(tmp);
}
sort(s.begin(),s.end(),cmp);
string ans;
for(int i=0;i<s.size();i++){
ans+=s[i];
}
return ans;
}
};
/*
1. 字符串到整数
stringstream sstr(str);
int x;
sstr >> x;(即从sstr中提取数据)
2. 整数到字符串
stringstream sstr;
int x;
sstr << x;
string str = sstr.str();
*/
33丑数
把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
class Solution {
public:
int GetUglyNumber_Solution(int index) {
vector<int> ugly(index, -1);
if (index <= 0) return 0;
int idx2 = 0, idx3 = 0, idx5 = 0, i = 1;
ugly[0] = 1;
while (i<index)
{
int new2 = ugly[idx2] * 2;
int new3 = ugly[idx3] * 3;
int new5 = ugly[idx5] * 5;
int tempVal = min(min(new2, new3), new5);
if (tempVal == new2)
idx2++;
if (tempVal == new3)
idx3++;
if (tempVal == new5)
idx5++;
ugly[i] = tempVal;
i++;
}
return ugly[index - 1];
}
};
34第一个只出现一次的字符
在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写).
class Solution {
public:
//全部字母则可以用一个26*2的数组存,字符值到下标有映射关系,这里求第一个,排序要带下标就比较烦
int FirstNotRepeatingChar(string str) {
int len=str.size();
int mp[53],id[53];
memset(mp,0,sizeof(mp));
memset(id,0,sizeof(id));
for(int i=0;i<len;i++){
if(str[i]<='Z')mp[str[i]-'A'+1]++,id[str[i]-'A'+1]=i;
if(str[i]>='a')mp[str[i]-'a'+27]++,id[str[i]-'a'+27]=i;
}
int ans=100;
for(int i=1;i<53;i++){
if(mp[i]==1){
ans=ans<id[i]?ans:id[i];
}
}
if(ans==100)return -1;
return ans;
}
};
35数组中的逆序对
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007
class Solution {
public:
vector<int> mvDataBack;//临时数组
long long count = 0;//答案是全局变量
int InversePairs(vector<int> data) {//传入数据求逆序数
if(data.empty())return 0;//无数就是0
mvDataBack.resize(data.size());//设置大小就是DATA的大小
split(data,0,data.size()-1);//进行分裂
return count%1000000007;//答案输出
}
void split(vector<int> &data,int start,int end){//传入向量,左界,右界
if(start>=end)return;//只有一个数就跳出了
split(data,start,(end-start)/2+start);//分裂左半区间
split(data,(end-start)/2+start+1,end);//分裂右半区间
merge(data,start,end);//合并整个区间
for(int i=start;i<=end;i++)data[i] = mvDataBack[i];//把临时数组原封不动赋回原数组
}
void merge(vector<int> &data,int start,int end){
int ind = end;//临时数组整个大扫描指针
int SplitPos = start+(end-start)/2;//区分位置
int left = SplitPos,right = end;//扫描指针从右界起
while(left>=start&&right>SplitPos){//两个指针都未到左界
if(data[right]>data[left])//右边的数较大,没有构成逆序数
mvDataBack[ind--] = data[right--]; //用右半区章数赋值
else{//左边的数较大,就要计COUNT
mvDataBack[ind--] = data[left--]; //赋值
count += (right-SplitPos); //统计count,当前右半区间的下标到分裂点的距离就是增加的逆序数对
}
}
while(left>=start)//扫描指针未到左界
mvDataBack[ind--] = data[left--];//赋值
while(right>SplitPos)//扫描指针未到右界
mvDataBack[ind--] = data[right--]; //赋值 //这里无需再进行count的统计
}
};
36两个链表的第一个公共结点
输入两个链表,找出它们的第一个公共结点。
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
set<ListNode*> st;
ListNode* p=pHead1;
while(p!=NULL){
st.insert(p);
p=p->next;
}
p=pHead2;
while(p!=NULL){
if(st.find(p)!=st.end()){
return p;
}
p=p->next;
}
return NULL;
}
};
37数字在排序数组中出现的次数
统计一个数字在排序数组中出现的次数。
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k) {
int ans=0;
sort(data.begin(),data.end());
for(int i=0;i<data.size();i++){
if(data[i]==k)ans++;
if(data[i]>k)return ans;
}
return ans;
}
};
38二叉树的深度
输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
int dfs(TreeNode* r,int dep){
if(r==NULL)return dep;
int d1=dfs(r->left,dep+1);
int d2=dfs(r->right,dep+1);
return d1>d2?d1:d2;
}
int TreeDepth(TreeNode* pRoot)
{
return dfs(pRoot,0);
}
};
39平衡二叉树
输入一棵二叉树,判断该二叉树是否是平衡二叉树。
class Solution {
public:
int fl=1;
//深搜每次返回当前子树的深度,函数中判断到如果有绝对值大于一就清标记位
int dfs(TreeNode* r,int dep){
if(r==NULL)return dep;
int d1=dfs(r->left,dep+1);
int d2=dfs(r->right,dep+1);
if( d1-d2<-1 || d1-d2 >1 ) fl=0;
return d1>d2?d1:d2;
}
bool IsBalanced_Solution(TreeNode* pRoot) {
int d=dfs(pRoot,1);
if(fl==0)return false;
else return true;
}
};
40数组中只出现一次的数字
一个整型数组里除了两个数字之外,其他的数字都出现了偶数次。请写程序找出这两个只出现一次的数字。
class Solution {
public:
void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
sort(data.begin(),data.end());
int fl=1;
for(int i=0;i<data.size();i++){
if(data[i]==data[i+1]){
i++;
continue;
}
if(fl==1){
*num1=data[i];
fl++;
}
else if(fl==2){
*num2=data[i];
return ;
}
}
}
};