MS100 [061-070]

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 个丑数。

思路:根据定义可知,后面的丑数肯定是前面已知丑数乘以235得到的。

  我们假设一个数组中已经有若干丑数,并且这些丑数是按顺序排列的,我们把现有的最大丑数记为max,则下一个丑数肯定是前面丑数乘以235得到的。不妨考虑乘以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);
    }
}

MS100 [068]
把数组排成最小的数

题目:输入一个正整数数组,将它们连接起来排成一个数,输出能排出的所有数字中最小的
一个。
例如输入数组{32, 321},则输出这两个能排成的最小数字32132。
请给出解决问题的算法,并证明该算法。
思路:相当于给数组中的元素排序,取min(a,b)为ab和ba中的较小值。由于要考虑溢出问题,所以可以分两段考虑。

posted @ 2012-10-09 16:36  moonswap  阅读(131)  评论(0编辑  收藏  举报