MS100 [061]
找出数组中两个只出现一次的数字
题目:一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。
思路:使用异或运算。
第一遍,全部异或,得到A,A中至少有一位为1,记为t位。
第二遍,对数组中的任意一个数,若t位为1,则与C异或,若t位为0,则与D异或。最后的C,D即为所求。
MS100 [062]
找出链表的第一个公共结点
题目:两个单向链表,找出它们的第一个公共结点。
思路:第一遍遍历两个链表,若尾指针相同则相交(若是循环链表,取任意一个循环中的节点即可),并且得到两个链表的长度。第二遍先让长的链表遍历他们的差值步,然后同步遍历两个链表,并比较是否相等。
MS100 [064]
寻找丑数
题目:我们把只包含因子2、3 和5 的数称作丑数(Ugly Number)。例如6、8 都是丑数,
但14 不是,因为它包含因子7。习惯上我们把1 当做是第一个丑数。求按从小到大的顺序的第1500 个丑数。
思路:根据定义可知,后面的丑数肯定是前面已知丑数乘以2,3,5得到的。
我们假设一个数组中已经有若干丑数,并且这些丑数是按顺序排列的,我们把现有的最大丑数记为max,则下一个丑数肯定是前面丑数乘以2,3,5得到的。不妨考虑乘以2得到的情况,我们把数组中的每一个数都乘以2,由于原数组是有序的,因为乘以2后也是有序递增的,这样必然存在一个数M2,它前面的每一个数都是小于等于max,而包括M2在内的后面的数都是大于max的,因为我们还是要保持递增顺序,所以我们取第一个大于max的数M2。同理对于乘以3的情况,可以取第一个大于max的数M3,对于乘以5的情况,可以取第一个大于max的数M5。
最终下一个丑数取:min{M2,M3,M5}即可
int mymin(int a, int b, int c)
{
int temp = (a < b ? a : b);
return (temp < c ? temp : c);
}
int FindUgly(int n) //
{
int* ugly = new int[n];
ugly[0] = 1;
int index2 = 0;
int index3 = 0;
int index5 = 0;
int index = 1;
while (index < n)
{
int val = mymin(ugly[index2]*2, ugly[index3]*3, ugly[index5]*5); //竞争产生下一个丑数
if (val == ugly[index2]*2) //只需要产生这个丑数的index*向后挪一位,因为其他数字必定比当前的丑数大。
++index2;
if (val == ugly[index3]*3) //这里不能用elseif,因为可能有两个最小值,这时都要挪动;
++index3;
if (val == ugly[index5]*5)
++index5;
ugly[index++] = val;
}
/*/
for (int i = 0; i < n; ++i)
cout << ugly[i] << endl;
//*/
int result = ugly[n-1];
delete[] ugly;
return result;
}
MS100 [065]
输出1 到最大的N 位数
题目:输入数字n,按顺序输出从1 最大的n 位10 进制数。比如输入3,则输出1、2、3 一直到最大的3 位数即999。
思路:(自己想的)考虑到N可能无限大,设置一个N位的数组,然后采用递归的方式,每次递归给当前位增加1,然后递归到下一位中,在最后一位时输出。注意若高位为0,则不输出。
#include <iostream>
using namespace std;
void Output(int* a,int n,int index){
if(index == n){
int first = -1;
while(a[++first] == 0);
for(int i=first;i<n;i++)cout<<a[i];
cout<<endl;
return;
}
for(int i=0;i<=9;i++){
a[index]=i;
Output(a,n,index+1);
}
}
int main(){
int n;
cin>>n;
int* a = new int[n];
Output(a,n,0);
return 0;
}
MS100 [066]
颠倒栈
题目:用递归颠倒一个栈。例如输入栈{1, 2, 3, 4, 5},1 在栈顶。
颠倒之后的栈为{5, 4, 3, 2, 1},5 处在栈顶。
思路:直接递归,每次把栈顶的元素移到pop出这个元素后的栈的底部。
void Reverse(Stack stack){
if(!stack.empty()){
Object o = stack.pop();
Reverse(stack);
InsertToBottom(stack,o);
}
}
void InsertToBottom(Stack stack,Object o){
if(stack.empty()){
stack.push(o);
}
else{
Object o2 = stack.pop();
InsertToBottom(stack,o);
stack.push(o);
}
}
把数组排成最小的数
题目:输入一个正整数数组,将它们连接起来排成一个数,输出能排出的所有数字中最小的
一个。
例如输入数组{32, 321},则输出这两个能排成的最小数字32132。
请给出解决问题的算法,并证明该算法。
思路:相当于给数组中的元素排序,取min(a,b)为ab和ba中的较小值。由于要考虑溢出问题,所以可以分两段考虑。