二维数组中的查找
题目描述
在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样一个二维数组和一个整数,判断数组中是否含有该整数。
解题思路:矩阵是有序的,从左下角来看,向上数字是递减的,向右数字是递增的,因此从左下角开始查找,当要查找的数字比左下角大时,右移一步;当要查找的数字小时,向上移动一步。
/*
@param: arr二位数组,target要查找的数字
@return: 当二位数组中存在要找查找的数字,则返回 1,否则返回 0
*/
int find(int arr[][N], int target)
{
int i = N - 1; //从左下角开始
int j = 0;
while(i >= 0 && j < N)
{
if(target == arr[i][j]) //找到要查找的数字
return 1;
if(target > arr[i][j]) //比左下角的数字大,右移一步
j++;
else //比左下角的数字小,向上移动一步
i--;
}
return 0;
}
不用加减乘除做加法
题目描述
写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/ 四则运算符号。
解题思路:用三步走的方式计算二进制值相加:
- 相加各位的值,不算进位。二进制每位相加就相当于各位做异或(^)操作。
- 计算进位值。相当于各位做与(&)操作,再左移一位。
- 重复上述两步,直到进位为0,则跳出循环。
exp:5(101)7(0111)
- 101^111 == 010
- (101&111)<<1 == 1010
- 重复上面两步,0010 ^1010 == 1000, (0010&1010)<<1 ==0100.
再重复,1000^0100 == 1100, (1000&0100)<<1 ==0,跳出循环,返还1100(12)。
int Add(int num1, int num2)
{
int sum, carry;
while(0 != num2)
{
//对应位相加但不进位,用异或实现
sum = num1^num2;
//记下进位,用与 和 移位实现
carry = (num1&num2)<<1;
num1 = sum;
num2 = carry;
}
return num1;
}
替换空格
题目描述
请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为 I Am A Handsome Boy. 则经过替换之后的字符串为I%20Am%20A%20Handsome%20Boy.
解题思路:从前往后替换,后面的字符要不断地往后移动,要多次移动,所以效率低下。从后往前移动,先计算需要多少空间,然后从后往前移动,则每个字符只会移动一次,这样效率更高一点。
/*
@param: str字符串
*/
void replaceSpace(char *str)
{
int Oldlen = 0; //记录字符串原来的长度
int cnt = 0; //记录空格的数量
int Newlen; //记录插入后的长度
while(str[Oldlen] != '\0') //遍历一遍字符串找出空格的数量
{
if(str[Oldlen] == ' ')
cnt++;
Oldlen++;
}
Newlen = Oldlen + 2*cnt; //插入后的长度,不用减一因为隐藏个'\0'也要算上
if(Newlen > max_size) //如果计算后的长度大于总长度就无法插入
return ;
while(Oldlen >= 0 && Newlen > Oldlen) //放字符
{
if(str[Oldlen] == ' ') //碰到空格就替换
{
str[Newlen--] = '0';
str[Newlen--] = '2';
str[Newlen--] = '%';
}
else //不是空格就将Oldlen指向的字符放入Newlen指向的位置
str[Newlen--] = str[Oldlen];
Oldlen--; //不管是if还是else,Oldlen都要前移
}
}
反转链表
题目描述
输入一个链表,反转链表后,输出新的表头。
解题思路:
ListNode* ReverseList(ListNode* pHead)
{
if(NULL == pHead) //判断链表是否为空
return NULL;
ListNode* pre = NULL;
ListNode* next = NULL;
while(pHead)
{
next = pHead->next;
pHead->next = pre;
pre = pHead;
pHead = next;
}
return pre; //pre成为新的头结点
}
青蛙跳台阶
问题描述
一只青蛙一次可以跳上1一级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。(先后次序不同算不同的结果)
解题思路:跟斐波那契数列一样的解法,没啥好说的。
当n=1时,有1种跳法;
当n=2时,有2种跳法;
当n=3时,有3种跳法;
当n=4时,有5种跳法;
……
当n时;有f(n-1) +f(n-2)种跳法;
int jumpFloor(int number)
{
if(number <= 2)
return number;
int num1 = 1;
int num2 = 2;
int tmp;
int i;
for(i=2; i<number; i++)
{
tmp = num1 +num2;
num1 = num2;
num2 = tmp;
}
return num2;
}
变态台阶
题目描述
一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
解题思路:
f(1)=1
f(2) = f(2-1) + f(2-2) //f(2-2)表示2阶一次跳2级的次数
f(3) = f(3-1) + f(3-2) + f(3-3)
……
f(n) = f(n-1) + f(n-2) + f(n-3)+……+ f(n-(n-1)) +f(n-n)
说明:
- 这里的f(n)代表的是n个台阶有一次1,2,……n级的跳法数。
- n = 1时,只有1种的跳法,f(1) = 1
- n = 2时,会有两种跳法,一次1级或2级。f(2) = f(0) + f(1)
- n = 3时,会有三种跳法,一次1级、2级或3级。那么就是第一次跳出1级后面剩下: f(3-1); 第一次跳出2级,剩下 f(3-2); 第一次跳出3级,剩下 f(3-3)。因此结论为:f(3) = f(3-1) + f(3-2) + f(3-3)
- n = n时,会有n种跳法,一次1级、2级…n级。得出结论:f(n) = f(n-1) + f(n-2)+……+f(n-(n-1)) + f(n-n) ---->f(0) +f(1) + f(2) + f(3) + ……+ f(n-2) + f(n-1)。
可以简化为:f(n) = 2*f(n-1)- 得出结论:
f(n) : n = 0时 f(n) = 0;f(n) = 1时 f(n) = 1;n>=2时 f(n) = 2*f(n-1).
int jumpFloorII(int number)
{
if(0 == number || 1 == number)
return number;
int i;
int power = 2;
for(i=2; i<number; i++)
{
power *= 2;
}
return power;
}
调整数组顺序使奇数位于偶数前面
题目描述
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
示例:
输入:[1 2 3 4 5 6 7] |
---|
输出:[1 3 5 7 2 4 6] |
解题思路:
类似于冒泡排序,前偶后奇就交换。
void reOrderArray(int *array, int len)
{
int i, j;
for(i=0; i<len-1; i++)
{
for(j=len-1; j>i; j--)
{
//前偶后奇,则交换
if(!(array[j-1]&1) && array[j]&1)
{
array[j] = array[j]^array[j-1];
array[j-1] = array[j]^array[j-1];
array[j] = array[j]^array[j-1];
}
}
}
}