MS100 [021]
编程求解:
输入两个整数n 和m,从数列1,2,3.......n 中随意取几个数,
使其和等于m ,要求将其中所有的可能组合列出来.
思路:纯编程题,只能暴力求解。
MS100 [024]
反转单链表和合并链表
思路:反转注意处理头尾,编程题。
合并两个链表时,可用:
while(lista!=null || listb!=null){ if(listb==null || lista->value <= listb-> value){ ... } else{ ... } }MS100 [027]
跳台阶问题
题目:一个台阶总共有n 级,如果一次可以跳1 级,也可以跳2 级。
求总共有多少总跳法,并分析算法的时间复杂度。
题目:一个台阶总共有n 级,如果一次可以跳1 级,也可以跳2 级。
求总共有多少总跳法,并分析算法的时间复杂度。
思路:Fibonacci数列,f(n)=f(n-1)+f(n-2), f(1)=1, f(2)=2。
MS100 [028]
整数的二进制表示中1 的个数
题目:输入一个整数,求该整数的二进制表达中有多少个1。
例如输入10,由于其二进制表示为1010,有两个1,因此输出2。
题目:输入一个整数,求该整数的二进制表达中有多少个1。
例如输入10,由于其二进制表示为1010,有两个1,因此输出2。
思路:方案一,n&(n-1)会把n的二进制表示中最右一位的1置为0(正负数皆如此)。
int c=0; while (n!=0) { n=n & (n-1); c++; }方案二,用sizeof计算整数的字节数,然后乘8。将1每次左移一位,并与n做与运算。
MS100 [029]
栈的push、pop序列
题目:输入两个整数序列。其中一个序列表示栈的push顺序,
判断另一个序列有没有可能是对应的pop顺序。
题目:输入两个整数序列。其中一个序列表示栈的push顺序,
判断另一个序列有没有可能是对应的pop顺序。
思路:使用一个栈模拟或者推理若将入栈按自然数编号,则出栈顺序中,出现在任意一个数字之后的所有比它小的数字一定呈逆序排列,即不可能出现3,1,2的出栈顺序,但可以出现1,2,3或者1,3,2或者3,2,1或者2,3,1或者2,1,3。
MS100 [030]
在从1 到n 的正数中1 出现的次数
题目:输入一个整数n,求从1 到n 这n 个整数的十进制表示中1 出现的次数。
题目:输入一个整数n,求从1 到n 这n 个整数的十进制表示中1 出现的次数。
思路:计算当某位为1时,其他位数可能出现的数字和。
例如ABCD,
当B小于1时,一共有100~199的100个+(A-1)*100个;
当B等于1时,一共有100~199的100个+(A-1)*100个+CD+1个;
当B大于1时,一共有100~199的100个+(A-1)*100个+A100~A199的100个;
类似的题有从1到n中0出现的次数,比上题稍复杂,因为0不能做数字的第一个字符。
例如ABCD,
当B等于0时,(A-1)*100个+CD+1个;
当B大于0时,(A-1)*100个+A000~A099的100个;
MS100 [035]求一个矩阵中最大的二维矩阵(元素和最大).如:
1 2 0 3 4
2 3 4 5 1
1 1 5 3 0
中最大的是:
4 5
5 3
1 2 0 3 4
2 3 4 5 1
1 1 5 3 0
中最大的是:
4 5
5 3
思路:每次将第i行到第j行的数据压缩成一行,然后用求最大字段和的动态规划算法。复杂度O(n^3)。
MS100 [036]
谷歌笔试:
n 支队伍比赛,分别编号为0,1,2。。。。n-1,已知它们之间的实力对比关系,存储在一个二维数组w[n][n]中,w[i][j] 的值代表编号为i,j 的队伍中更强的一支。所以w[i][j]=i 或者j,现在给出它们的出场顺序,并存储在数组order[n]中,比如order[n] = {4,3,5,8,1......},那么第一轮比赛就是4 对3, 5 对8。.......胜者晋级,败者淘汰,同一轮淘汰的所有队伍排名不再细分,即可以随便排,下一轮由上一轮的胜者按照顺序,再依次两两比,比如可能是4 对5,直至出现第一名。编程实现,给出二维数组w,一维数组order 和用于输出比赛名次的数组result[n],求出result。
n 支队伍比赛,分别编号为0,1,2。。。。n-1,已知它们之间的实力对比关系,存储在一个二维数组w[n][n]中,w[i][j] 的值代表编号为i,j 的队伍中更强的一支。所以w[i][j]=i 或者j,现在给出它们的出场顺序,并存储在数组order[n]中,比如order[n] = {4,3,5,8,1......},那么第一轮比赛就是4 对3, 5 对8。.......胜者晋级,败者淘汰,同一轮淘汰的所有队伍排名不再细分,即可以随便排,下一轮由上一轮的胜者按照顺序,再依次两两比,比如可能是4 对5,直至出现第一名。编程实现,给出二维数组w,一维数组order 和用于输出比赛名次的数组result[n],求出result。
思路:将每组中的胜者保存在数组的前半部分,注意考虑边界。
MS100
[037]
最长联接字符串
有n个长为m+1的字符串,
如果某个字符串的最后m个字符与某个字符串的前m个字符匹配,则两个字符串可以联接,
问这n个字符串最多可以连成一个多长的字符串,如果出现循环,则返回错误。
思路: 把每个字符串看成一个图的顶点,两个字符串匹配就连一条有向边。相当于判断一个有向图是否有环以及求它的直径。
MS100 [038]
百度面试:
1.用天平(只能比较,不能称重)从一堆小球中找出其中唯一一个较轻的,使用x次天平,最多可以从y个小球中找出较轻的那个,求y与x的关系式
2.有一个很大很大的输入流,大到没有存储器可以将其存储下来,而且只输入一次,如何从这个输入流中随机取得m个记录
3.大量的URL字符串,如何从中去除重复的,优化时间空间复杂度
思路:1. y=3^x
2. 对前m个数,直接存储,对于后来的第k个数,产生一个0~k的随机数,若数值在0~m之间,替换相应的数。
3.构造一个hash函数,把url适当散列到若干个,比如1000个小文件中,然后在每个小文件中去除重复的url,再把他们合并。
原理是相同的url,hash之后的散列值仍然是相同的。
MS100 [039]
求割点
求一个有向连通图的割点,割点的定义是,如果除去此节点和与其相关的边,
有向图不再连通,描述算法。
思路:在深度优先树中,根结点为割点,当且仅当他有两个或两个以上的子树。
其余结点v为割点,当且仅当存在一个v的后代结点s,s到v的祖先结点之间没有反向边。
记发现时刻dfn(v)为一个节点v在深度优先搜索过程中第一次遇到的时刻。
记标号函数low(v) = min(dfn(v), low(s), dfn(w))
s是v的儿子,(v,w)是反向边。
low(v) 表示从v或v的后代能追溯到的标号最小的节点。
则非根节点v是割点,当且仅当存在v的一个儿子s,low(s) > = dfn(v)。
算法先从某个节点做深度优先递归搜索,并设置所遇到节点的dfn值,然后递归返回求他的low值。
MS100 [040]
1)一串首尾相连的珠子(m个),有N种颜色(N<=10),设计一个算法,取出其中一段,要求包含所有N中颜色,并使长度最短。并分析时间复杂度与空间复杂度。
2)设计一个系统处理词语搭配问题,比如说 中国 和人民可以搭配,则中国人民 人民中国都有效。
要求:
*系统每秒的查询数量可能上千次;
*词语的数量级为10W;
*每个词至多可以与1W个词搭配
当用户输入中国人民的时候,要求返回与这个搭配词组相关的信息。
思路:1)就是给一个很长的字符串str 还有一个字符集比如{a,b,c} 找出str里包含{a,b,c}的最短子串。
比如,字符集是a,b,c,字符串是abdcaabcx,则最短子串为abc。
用两个变量 front,rear,指向一个的子串区间的头和尾,用一个int cnt[255]={0}记录当前这个子串里 字符集a,b,c 各自的个数,一个变量sum记录字符集里有多少个了。
开始时front和rear都指向头部。rear 一直加,更新cnt[]和sum的值,直到 sum等于字符集个数。然后front++,直到cnt[]里某个字符个数为0,这样就找到一个符合条件的字串了。
继续前面的操作,就可以找到最短的了。