1.        如何从链表中删除重复元素(NO2_DeleteDup.java)

1)        遍历链表,把遍历到的值存储到一个hashTable中,在遍历过程中,若当前访问的值在hashTable中,则删除这个数据。

2)        双重循环遍历

2.        如何找出单链表中倒数第K个元素(NO3_FindEndK)

定义两个指针p1、p2,p2比p1先行k-1步。当p2到达链表尾部时,p1为所求。

3.        如何实现链表反转(NO4_ReverseIteratively)

定义3个指针per,cur,next,改变指针的指向顺序,即让指针反转。

next = cur.next;

 

cur.next = per;

per = cur;

cur = next;

4.        如何从尾到头输出单链表(NO5_PrintReversely)

每访问一个节点,先递归输出它后面的节点,在输出该节点自身。

5.        如何寻找单链表的中间结点(NO6_SearchMid)

1)        定义两个指针pFast,pSlow,从头开始遍历。

2)        pFast一次走两步,pSlow一次走一步。

3)        当pFast到达链表尾部时,pSlow为所求。

6.        如何检查一个链表是否有环(NO7_IsLoop)

1)        定义两个指针fast,slow;

2)        fast一次走2步,slow一次走一步,从头开始遍历

3)        没走一次,比较fast和slow是否相等,若相等,则有环。若到结尾,都未相等,则无环。

7.        如何找到环的入口点(NO7_IsLoop)

1)        定义两个指针pFast,pSlow,从头开始遍历。

2)        根据方法6,找到pFast,pSlow的相遇节点pFast。

3)        将pSlow指向头结点,当pSlow与pFast再相遇时,二指针所指向的为所求。

8.        如何在不知道头指针的情况下删除指定节点(NO8_DeleteNode)

1)        如果指定结点是尾结点,则无法删除。因为不能将前驱结点的next指针置为空。

2)        若不是尾结点,则可以通过这个结点和后继结点的值,然后再删除后继结点来完成。

9.        如何判断两个链表是否相交(NO9_IsIntersect)

若两个链表相交,则两个链表必然有相同的尾结点。

1)        遍历链表h1,得到尾结点tail1。

2)        遍历链表h2,得到尾结点tail2。

3)        若tail1==tail2,则相交,否则不想交

10.    如果两个链表相交,如何找到它们相交的第一个结点(NO10_FirstMeetNode)

1)        分别计算两个链表h1和h2 的长度len1和len2。

2)        对链表h1遍历(len1-len2)个结点到结点p。

3)        此时同时遍历两个链表,直到遇到相同的结点为止,这个结点为所求。

11.    如何实现栈(NO11_MyStack)

可以采用数组与链表这两种方法来实现栈

12.    如何用O(1)的时间复杂度求栈中最小元素(NO12_MyStack_MIN_O1)

实现两个栈结构:一个栈elem用来存储数据,另一个栈min用来存储栈中最小元素。

1)        如果当前入栈元素比栈min的栈顶元素小,则把这个值压入保存最小元素的栈中。

2)        在出栈时,如果当前入栈的元素恰好为当前栈中的最小元素,栈min栈顶元素出栈,使得当前最小值变为其入栈之前的那个最小值。

13.    如何用两个栈模拟队列操作(NO13_MyQueue)

有两个栈,栈A和栈B,来模拟队列Q

1)        入队操作:栈A入栈。

2)        出队操作:分两种情况

a)        若栈B不为空,则栈B出栈操作。

b)        若栈B为空,栈A出栈并将其放入到栈B中,栈B出栈。

14.    如何用两个队列模拟栈的操作

两个队列,队列A和队列B,来模拟栈S

1)        入栈操作:队列A入队列

2)        出栈操作:

a)        队列A中的元素出队列,将其放入到队列B中。

b)        队列A中最后一个元素不入队列B中,输出该元素。

c)        队列B中元素放入的队列A中。

15.    选择排序(NO14_SelectSort)

每一趟从未排序的队列中选出最小的元素,与未排序队列中的第一个位置交换,并将未排队列的第一元素纳入到已排队列中。

16.    插入排序(NO15_InsertSort)

每趟把未排序队列的第一个元素,插入到前面已排序队列中。

17.    冒泡排序(NO16_BubbleSort)

从后往前,每趟把最小的元素放到前面。

18.    归并排序(NO17_Merge)

归并排序关键就2步:

1)        划分半子表

a)        递归前一半

b)        递归后一半

2)        合并字表

a)        分别将开头到中间和中间到结尾的元素放入到2个数组中(L和R)。

b)        每次从L和R中找出最小的放入到原数组中

19.    快排(NO18_QuitSort)

1)        分解。将a[i]放到正确的位置。将数组分成两个非空子序列,分别是:a[i]之前和a[i]之后。

2)        分别递归求解两个数组。

20.    希尔排序(NO19_ShellSort)

1)        选择一个步长序列t1,t2,…,tk,满足ti>tj(i<j),tk=1.

2)        按步长序列个数k,对待排序序列进行k趟排序。

3)        每趟排序,根据对应步长ti,将待排序列分割成ti个子序列,分别对各个子序列进行直接插入排序。

21.    堆排序(NO20_HeapSort)

1)        构建堆(不断的调整堆)

a)        找到该父结点的两个子节点。

b)        比较俩个子节点,找到最小的子节点。

c)        比较父结点和最小的子节点。若子节点小,则交换。

2)        交换堆顶元素与最后一个元素的位置,调整堆。每次调整堆使得最后一个元素在正确的位置。

22.    如何用移位操作实现乘法运算

把一个数向左移动n位,相当于把这个数乘以2的n次方。

23.    如何判断一个数是否为2的n次方(NO21_IsPower)

方法1:

1不断的乘以2,即i左移1位。若i==n,则n是2的次方。若到了i>n时,则n不是2的次方。

方法2:

利用若n是2的次方,则n的二进制数只有一个1。即m=n&(n-1),m=0则是,否则不是。

24.    如何求二进制数中1的个数(NO22_CountOne)

利用没执行一次n&(n-1)实际是将n所代表的二进制数中最后一个1去掉。

循环执行,直到n为0为止。

25.    如何寻找数组中的最小值与最大值(NO23_MaxMin)

维持两个变量max和min,遍历数组,用min标记最小值,用max标记最大值,每次取出一个元素,先与已找到的最小值比较,再与已找到的最大值比较。

26.    如何找出数组中第二大的数(NO24_SecondMax)

1)        定义两个变量max和secmax。

2)        遍历数组元素

a)        如果数组元素的值比最大数变量的值大,则secmax=max,max=a[i]。

b)        如果小于最大值,则与第二大值比较。若比第二大值大,则secmax=a[i];

27.    如何求最大子数组之和(NO25_MaxSubArray)

方法1:

1)        分别以a[0],a[1],…,a[n]开头的最大子数组和。

2)        每次遍历过程中,每加一个数后的和都要与maxSum比较,用maxSum标记最大子数组的和。

方法2:

         根据数组的最后一个元素a[n-1]与最大子数组的关系分为以下3中情况:

1)        最大子数组包含a[n-1],即以a[n-1]结尾。

2)        a[n-1]单独构成最大子数组。

3)        最大子数组不包含a[n-1],那么求a[1,…,n-1]的最大子数组可以转换为求a[1,…,n-2]的最大子数组。

即遍历数组,每一趟的最大子数组为nAll=max{nEnd+a[i],a[i],nAll}

28.    如何确定最大子数组的位置(NO25_MaxSubArray)

1)        定义两个变量,begin和end

2)        当nSum值小于0时,最大子数组重新计算。即nStart = i;

3)        当nSum值大于maxSum时,maxSum = nSum;begin=nStart;end=I;

29.    如何找到数组中重复元素最多的数(NO26_MostFrequentInArray)

1)        使用Map,将元素放入到Map中。重复一次value值+1;

2)        遍历Map,找到value最大值,和对应的元素(key);

30.    如何求数组中两两相加等于20的组合种数

1)        对数组排序

2)        while(begin<end);如果begin+end<sum,则begin++。如果begin+end>sum,则end--;

如果begin+end=sum,则输出并且begin++,end--。

31.    如何把一个数组循环右移k位

原数组根据k分成两个数组,后k个元素为一个数组,剩余元素是一个数组。

1)        数组1逆序

2)        数组2逆序

3)        整个数组逆序

32.    如何找出数组中第K个最小的数(NO29_GetKMin)

采用快排的思想来实现

1)        选取一个数,快排放到正确的位置

2)        若它的位置是k-1,则为所求。

3)        若它的位置<k-1,递归右半部分

4)        若它的位置>k-1,递归左半部分

33.    如何找出数组中只出现一次的数字(NO30_FindNoDouble)

问题描述:一个整型数组里除了一个数字之外,其他数字都会出现两次。找出这个只出现1次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。

利用任何一个数字异或自己都等于0的特点。从头到尾异或数组中的每一个数字,那么最终的结果刚好是只出现1次的数字。

34.    如果题目改为数组A中,一个整型数组里除了一个数字之外,其他数字都出现了3次,那么如何找出这个数字。(NO30_FindNoDouble)

1)        计算数组中所有数组对应的二进制数各个位置上出现1的次数。

2)        若某位上的结果不能被整除,则肯定目标数字在这一位上。

35.    如何找出数组中唯一重复的元素(NO31_FindDouble)

问题描述:数组a[N],1~N-1这N-1个数存放在a[N]中,其中某个数重复出现1次。要求每个数组元素只能访问一次,并且不用辅助存储空间。

1)        方法1:(a[N]全部数的和)-(1~N-1的和)=重复元素

2)        方法2:(a[N]全部数异或)异或(1~N-1异或)= 重复元素

36.    取值为[1,n-1]含n个元素的整数数组,至少存在一个重复数,在O(n)时间内找出其中任意一个重复数。(NO31_FindDouble)

取反法:遍历数组,如果遍历数组中元素i,那么把a[i]的值取反,如果i在数组中出现2次,那么a[i]会经过两次操作,a[i]的值跟原始的值相等。否则相反。

37.    如何用递归方法求一个整数数组的最大元素

递归求解“数组第一个元素”与“数组中其他元素所组成的子数组的最大值”的最大值

max(a[begin],findMax(a,begin+1))

38.    如何求数对只差的最大值

问题描述:数组中的一个数字减去它右边子数组中的一个数字可以得到一个差值,求所有可能的差值中最大值。

二分法:把数组2部分,左数组和右数组(递归求解)

1)        求左数组最大差值

2)        求右数组最大差值

3)        求左数组最大值-右数组最小值

4)        设置最大值和最小值

5)        比较3个值,求最大值

39.    如何求绝对值最小的数(NO34_MinAbsoluteValue)

问题描述:有一个升序排列的数组,数组中可能有正数、负数或0,求数组中元素的绝对值最小的数。

1)        取数组的中间值a[mid]。

2)        若a[mid]=0,即为所求。

3)        若a[mid]>0,若a[mid-1]<0,则比较2者绝对值,小的为所求。否则递归左边。

4)        若a[mid]<0,若a[mid+1]>0,则比较2者绝对值,小的为所求。否则递归右边。

40.    如何求数组中两个元素的最小距离(NO35_MinDist)

问题描述:给定一个数组,数组中含有重复元素,给出两个数n1和n2,求这两个数字在数组中所出现位置的最小距离。

1)        定义两个变量n1_index和n2_index

2)        每遇到一次n1或n2时,标记相应的index,比较求得最小的minDist。

41.    如何求指定数字在数组中第一次出现的位置(NO36_FindIndex)

问题描述:给定数组a={3,4,5,6,7,8,9,8},这个数组中邻居元素之差为1,给定数字9,它在数组中第一次出现的位置的下标为8。

1)        从数组第一个元素开始,把当前位置的值与t比较。若相等则返回。

2)        若不想等,则从i+|t-a[i]|开始查找。

42.    如何对数组的两个子有序段进行合并(NO37_VoidSort)

问题描述:数组a[0,mid-1]和a[mid,n-1]是各自有序的,对数组a[0,n-1]的两个子有序段进行合并,得到a[0,n-1]整体有序。要求空间复杂度为O(1)

基本思想是使a[0,mid-1]中的所有数都小于a[mid],再加上2数组各自有序,则a[0,n-1]为所求。

1)        遍历a[0,mid-1]数组,每一个元素都与a[mid]比较。

2)        若a[i]<a[mid],则继续。若a[i]>a[mid],则

a)        交换a[i]与a[mid]。

b)        找到a[mid]在a[mid,n-1]中的位置。

43.    如何计算两个有序整型数组的交集(NO38_FindMix)

1)        建立一个容器,该容器用来存放相交元素

2)        遍历2个数组,分别比较两个数组,移动值小的数组指针。若相等放入到容器中。

44.    如何判断一个数组中数值是否是连续相邻(NO39_IsContinuous)

问题描述:

1)        5个数值允许是乱序的,例如{8,7,5,0,6}

2)        0可以通配任意数值

3)        0可以出现多次

4)        全0算连续,只有一个非0算连续

思路:连续最主要的特点就是相邻值相差1,只要涉及到连续这就是一个隐含条件

1)        遍历数组,找到数组中最大值max和最小值min。

2)        若max-min<n-1,则表示连续。否则,不连续。

45.    如何求解数组中反序对的个数(NO40_ReverseCount)

问题描述:给定一个数组a,如果a[i]>a[j](i<j),那么a[i]与a[j]被称为一个反序对,例如{1,5,3,2,6},共有(5,3)、(5,2)和(3,2)三个反序对。

分治思想:利用归并排序的方法,在归并排序中加一个计数器记录逆序个数。

当L[]>R[]时,计数器reverseCount+=mid-(i-1)

46.    如何求解最小三元组距离(NO41_MinDist)

问题描述:即在3个升序数组中分别找一个数a[i]、b[j]、c[k]使得

Distance = max{|a[i]-b[j]|,|a[i]-c[k]|,|b[j]-c[k]|}值最小。

基本思想:假设取出来的3个数为a,b,c,且a<=b<=c。那么c-a为所求。

1)        从3个数组中取出第一个元素

2)        求curdist,软后minDist比较,求得最小的值。

3)        3个数中最小的数对应的数组,移动该数组的下标。

4)        直到其中一个数组遍历完毕为止。

47.    如何实现字符串的反转(NO42_SwapWord)

问题描述:把一个句子的单词进行反转,例如“how are you”,翻转后为“you are how”。

1)        整个字符串反转“uoy era woh”

2)        每个单词反转“you are how”

48.    如何判断两个字符串是否由相等的字符组成(NO43_Compare)

问题描述:有相同的字符组成是指组成两个字符串的字母以及各个字母的个数是一样的,仅顺序不同而已。

1)        将2个字符串转化为2个byte数组。

2)        对两个byte数组排序

3)        将2个byte数组转化为字符串

4)        比较两个字符串

49.    如何删除字符串中重复的字符(NO44_RemoveDup)

问题描述:删除字符串中重复的字符

1)        申请一个大小为256的int型数组,用来记录每个字符出现的次数,初值为0。

2)        字符的编号作为数组的下标,在遍历字符数组时,如果这个字符出现次数为0,那么把它置为1.如果这个字符出现次数为1,把这个字符串置为’\0’。

3)        遍历字符串,去掉’\0’。

50.    如何统计一行字符中有多少个单词(NO45_WordCount)

1)        判断是一个单词的标准是:空+非空=>一个单词,计数器+1;

2)        用word标记连续出现的空。Word=0,表示前一个字符是空;若word=1,意味着前一个字符非空。

51.    如何按要求打印数组的排列情况(NO46_FirstSearch)

问题描述:针对1、2、2、3、4、5这6个数字,写一个函数,打印出所有不同的排列,要求“4”不能在第3位,“3”与“5”不能相连。

1)        用1、2、2、3、4、5这6个数作为6各节点,构造一个无向连通图。除了“3”与“5”不连通外,其他都连通。

2)        分别对这6个结点出发对图做深度优先遍历。若第三个数不是“4”,则把这个数字放到集合Set中。

3)        遍历Set集合,打印所有结果。

52.    如何输出字符串的所有组合(NO47_HowCombin)

问题描述:假设字符串中的所有字符都不重复,如何输出字符串的所有组合

思路:用长度为n的01字符串表示输出结果中包含某个字符。例如:001表示不含a,b,只含c。

1)        把第一位的1变为0;

2)        把第一个0变为1;

3)        把变化后的应该显示的字符放到cache中

4)        输出结果

53.    如何实现二叉排序树(NO48_BinaryTree)

1)        创建一个结点

2)        比较data与当前结点data的大小

a)        若data>curNode.data,curNode = curNode.right

b)        否则,curNode = curNode.left;

3)        直到当前结点为空时,parent.left = newNode或parent.right =newNode;

54.    如何实现层序遍历二叉树(NO48_BinaryTree)

主要思路:借助一个队列实现

1)        把根节点放入到队列中

2)        从队列中取出一个元素,输出data,然后将孩子结点放入队列中。

3)        直到队列为空。

55.    已知先序遍历和中序遍历,如何求后序遍历(NO48_BinaryTree)

1)        先序序列第一个为根结点

2)        以根结点在中序中定位

3)        左子树=中序中左部份构建左子树

4)        右子树=中序中右部份构建右子树

5)        head.left = 左子树

6)        head.right = 右子树

56.    如何求二叉树中结点的最大距离(NO48_BinaryTree)

问题描述:结点距离是指这两个结点之间边的个数。写一个程序求一棵二叉树中相距最远的两个结点之间的距离。

         结点内容加两个变量:leftMaxDis和rightMaxDis;

1)        初始化根节点

2)        递归左子树

3)        递归右子树

4)        求左子树中距离根节点的最大距离

5)        求右子树中距离根节点的最大距离

6)        获取最大距离max = root.leftMaxDis+root.rightMaxDis

57.    如何消除嵌套的括号(NO49_ChangeStr)

问题分析:给定一个如下字符串(1,(2,3),(4,(5,6),7))

1)        判断表达式中只有数字、逗号和括号这几种字符,如果有其他字符出现则是非法的。

2)        判断括号是否匹配,若碰到“(”,则把括号的计数器+1;

3)        如果碰到“)”,此时在判断计数器是否大于1。若是,则把计数器-1,否则非法表达式。

58.    如何不使用比较运算符就可求出两个数的最大值和最小值

1)        Max(a,b) = (a+b+Math.abs(a-b))/2;

2)        Min(a,b) =(a+b-Math.abs(a-b))/2;

 

 

 

 

 

 

 

 

 

59.    给定一个整数N,那么N的阶乘N!末尾有多少个0?(NO50_CountZero)

思路:,那么N!末尾有M个0。对N!进行质因数分解,,由10=2*5,故M=min(X,Y)。由能被2整除的数出现的频率比能被5整除的频率大,故M=Z。

即计算1~N的因式分解中5的指数,然后求和。

总结:N!中含质因数5的个数为所求

60.    求N!的二进制表示中最低位1的位置(NO51_LowestOne)

N!中含质因数2的个数+1为所求。

61.    一个ID的发帖数超过总贴数的一半,如何找出这个ID

思路:若“水王”的ID出现半数以上,则在ID数组中每次删除2个不同的ID,那么当遍历一次后最后剩下的变为所求。

62.    写一个函数f(N),返回1到N之间出现1的个数,比如f(12)=5;

设N=abcde。从低位到高位计算每一位出现1的个数,累计的和为所求。

这样讲N分为3部分:低位lower、当前位cur、高位high。当前位出现1的个数与当前位的值有关。

Cur=0时:出现1的个数=high*当前位数

Cur=1时:出现1的个数=high*当前位数+lower+1

Cur>1时:出现1的个数=(high+1)*当前位数

其中:lower=n-(n/factor)*factor

           Cur=(n/factor)%10

           Hight=n/(factor*10)

63.    满足条件“f(N)=N”的最大的N是多少。