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中的较小值。由于要考虑溢出问题,所以可以分两段考虑。