1.对上万个员工的年龄进行排序,时间复杂度不超过O(n),空间复杂度为常数级别(特点:带排序的值有一个范围)
void sortAge(int age[],int length){
const int oldestage = 99;
int timeAge [oldestage + 1]={0}; //第i个位置存i岁的人的个数
for(int i = 0;i<length ; ++i){
if( age[i]<0 || age[i] >99)
++ timeage [ age[i]] ;
}
int index = 0;
for(int i = 0 ;i<oldestage ; ++i){
for(int j = 0 ;j<timeage[i];++j)
{ age[index] = i; //连续timeage[i]个人都是i岁
++index;
}
}
}
2.旋转数组
输入一个递增数组的旋转数组,输出旋转数组的最小元素。
旋转之后的数组实际上可以划分为两个排序的子数组(采用二分查找的思想),用两个指针分别指向第一个元素和最后一个元素,找到中间的元素,判断中间位置前后元素的之判断该位置实在前段数组还是后段数组,
还是两段数组的边界。
递归与循环
递归的缺陷:递归会导致栈溢出:调用层级太多的时候 ,就会超出栈的容量。
采用递归求菲薄纳妾前n项和
long long Fib(unsigned int n){
if(n <= 0)
return 0;
if(n == 1 )
return 1;
return Fib(n-1)+Fib(n-2);
}
上述解法会重复计算大量的数。
采用自底向上的循环解法 从Fib(0) 和 Fib(1)开始计算
long long Fib(int n ){
int res[2] = {0 ,1};
if(n < 2)
return res[n];
long long Fib1 = 1; // Fib(1)
long long Fib2 = 0; //Fib(0)
long long FibN = 0;
for(unsigned int i = 0; i <= n ; ++i){ //开始计算Fib(2)直到Fib(n)
FibN = Fib1 + Fib2;
Fib1 = FibN;
Fib2 =Fib1;
}
}
3.给定链表头指针 和节点的指针,在O(1)时间内删除链表的结点
将该节点下一个节点的位置的值将该节点的值覆盖,将下一个节点删除。
4.链表中的 倒数第k个节点:输入一个节点,输出该链表的倒数第k个节点(利用快指针慢指针)
两个指针指向头节点,快指针先向前走k-1步,然后两个指针再一起移动,最后快指针到达链表末尾的时候慢指针指向倒数第k个节点。
5.链表反转:输入一个链表的头节点,输出反转后的链表的头节点。
为了反转这个单链表,我们先让头结点的next域指向结点2,再让结点1的next域指向结点3,最后将结点2的next域指向结点1,就完成了第一次交换,顺序就变成了Header-结点2-结点1-结点3-结点4-NULL,然后进行相同的交换将结点3移动到结点2的前面,然后再将结点4移动到结点3的前面就完成了反转,思路有了,就该写代码了:
LinkedList ReverseSinglyLinkedList(LinkedList list)
{
LNode *tmp = NULL;
LNode *p = NULL;
if (list == NULL)
{
return NULL;
}
tmp = list->next;
while (tmp->next != NULL)
{
p = tmp->next;
tmp->next = p->next;
p->next = list->next;
list->next = p;
}
return list;
}
6.调整数组的顺序,使奇数位于数组的前半部分,偶数位于后半部分。
解法:维护两个指针,第一个指针指向数组的第一个元素,只向后移动,
第二个指针指向数组的最后一个元素,只向前移动,在两个指针相遇前,如果第一个指针内容是偶数并且第二个指针的内容是奇数,交换两个指针的内容。
void ReOrder(int *pData,unsigned int length){
if(pData == NULL || length <1)
return ;
int *pBegin = pData;
int *pEnd = pData + length -1;
while (pBegin < pEnd ){
while(pBegin < pEnd &&( *pBegin %2 == 1))
++pBegin;
while(pBegin < pEnd &&( *pEnd %2 == 0))
--pEnd;
if(pBegin < pEnd){
*pBegin ^= *pEnd;
*pEnd ^= *pBegin;
*pBegin ^= *pEnd;
}
}
}
7.完成一个函数,输入一个二叉树,输出它的镜像
解法:先前序遍历树的每一个节点,当该节点存在子节点的时候,交换子节点的值。
8.顺时针转圈打印矩阵
9.二叉树中和为某一值的路径
10.二叉搜索树和双向链表:输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表,不能创建任何新节点,只能调整树中节点指针的指向。
解法:中序遍历的过程中,将前驱和后继连接起来
11.字符串的排列,输入一个字符串,打印出字符串中字符的所有排列。
把字符串看成两部分:第一部分是它的第一个字符,第二部分是其余的字符
首先求所有可能出现在第一个位置的字符(把第一个字符和后面所有字符交换)
接着对剩余的部分重复同样的操作
12.数组中出现次数超过一半的数
13.连续子数组的最大和;输入一个整型数组,数组里有正数和负数,求所有子数组的最大和,要求时间复杂度为O(n)
从第一个元素开始逐个向后扫描,计算到当前和,如果和<= 0 则前面的抛弃,在开始技术,并且不断根系当前和,知道扫描到最后一个元素。
14.在字符串中找出第一个只出现一次的字符
定义一个哈希表,