题目来自于
http://zhedahht.blog.163.com/blog/#m=0&t=1&c=fks_081075092084086069082074084070080087080066083082
非常感谢何海涛 July大神和众网友。
本博文初衷是为了方便自己准备面试,有一篇文章可以看所有的东西,省的翻来翻去。
代码是手打的Qt C++,解法中不考虑实现最简单的毫无难度的暴力解法了。
因为很短,不区分*.cc和*.hh文件了,都写在一起; 注释初衷也是为了自己理解。
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1.1程序员面试题精选100题(10)-排序数组中和为给定值的两个数字[算法]
题目描述:
输入一个已经按升序排序过的数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数字。要求时间复杂度是O(n)。如果有多对数字的和等于输入的数字,输出任意一对即可。
例如输入数组1、2、4、7、11、15和数字15。由于4+11=15,因此输出4和11。
分析与C++代码:
// 程序员面试题精选100题(10)-排序数组中和为给定值的两个数字[算法]
// 题目: 输入一个已经按升序排序过的数组和一个数字,在数组中查找两个数,
// 使得它们的和正好是输入的那个数字。要求时间复杂度是O(n)。
// 如果有多对数字的和等于输入的数字,输出任意一对即可。
// 例如输入数组1、2、4、7、11、15和数字15。由于4+11=15,因此输出4和11。
#include<iostream>
using namespace std;
bool findTwoNumbers(const int* arr, size_t arrLength, int target, int& index1, int& index2);
int main()
{
int test[] = {1, 2, 4, 11, 15};
size_t testLength = sizeof(test)/sizeof(test[0]);
int target = 15;
int index1 = 0, index2 = 0;
if (findTwoNumbers(test, testLength, target, index1, index2))
{
cout << test[index1] << " + " << test[index2] << " = " << target << endl;
}else
{
cout << "failed to find out such two numbers!" << endl;
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// 推荐解法: 两边逼近
// 如果我们不考虑时间复杂度,最简单想法的莫过去先在数组中固定一个数字,
// 再依次判断数组中剩下的n-1个数字与它的和是不是等于输入的数字。可惜这种思路需要的时间复杂度是O(n2)。
// 我们假设现在随便在数组中找到两个数。如果它们的和等于输入的数字,那太好了,
// 我们找到了要找的两个数字;如果小于输入的数字呢?我们希望两个数字的和再大一点。
// 由于数组已经排好序了,我们是不是可以把较小的数字的往后面移动一个数字?
// 因为排在后面的数字要大一些,那么两个数字的和也要大一些,就有可能等于输入的数字了;
// 同样,当两个数字的和大于输入的数字的时候,我们把较大的数字往前移动,因为排在数组前面的数字要小一些,
// 它们的和就有可能等于输入的数字了。
// 我们把前面的思路整理一下:最初我们找到数组的第一个数字和最后一个数字。
// 当两个数字的和大于输入的数字时,把较大的数字往前移动;当两个数字的和小于数字时,把较小的数字往后移动;
// 当相等时,打完收工。这样扫描的顺序是从数组的两端向数组的中间扫描。
//
// 如果数组未排序,先排序O(nlogn),如果是三个数的和,先固定数组里的一个数arr[0],在用
// 上面的方法找两个数=target-arr[0] for all arr[ii] O(n^2) in total
bool findTwoNumbers(const int* arr, size_t arrLength, int target, int& index1, int& index2)
{
if (arr == NULL || arrLength <= 0)
{
return false;
}
index1 = 0;
index2 = arrLength - 1;
while(index1 < index2)
{
// 细节,两个整数相加可能会溢出
long long curSum = arr[index1] + arr[index2];
if (curSum < target)
{
index1++;
}else if(curSum == target)
{
return true;
}else
{
index2--;
}
}
return false;
}
1.2 调整数组顺序使奇数位于偶数前面[算法]
题目描述:
输入一个整数数组,调整数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。要求时间复杂度为O(n)。
分析与C++代码:
// 程序员面试题精选100题(29)-调整数组顺序使奇数位于偶数前面[算法]
// 题目: 输入一个整数数组,调整数组中数字的顺序,使得所有奇数位于数组的前半部分,
// 所有偶数位于数组的后半部分。要求时间复杂度为O(n)。
#include<iostream>
#include<string>
using namespace std;
void myPrint(int arr[], size_t arrLength, string header)
{
cout << header << ": ";
for(size_t ii = 0; ii < arrLength; ++ii)
{
cout << arr[ii] << " ";
}
cout << endl;
}
bool oddEvenSort(int arr[], size_t arrLength);
int main()
{
int test[] = {2,4,6,8, 1, 3, 5, 7};
size_t testLength = sizeof(test)/sizeof(test[0]);
myPrint(test, testLength, "before");
if(oddEvenSort(test, testLength))
{
myPrint(test, testLength, "after");
}else
{
cout << "error!" << endl;
}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// 推荐解法: 前后交换
// 要求的是把奇数放在数组的前半部分,偶数放在数组的后半部分,因此所有的奇数应该位于偶数的前面。
// 也就是说我们在扫描这个数组的时候,如果发现有偶数出现在奇数的前面,我们可以交换他们的顺序,交换之后就符合要求了。
// 因此我们可以维护两个指针,第一个指针初始化为数组的第一个数字,它只向后移动;
// 第二个指针初始化为数组的最后一个数字,它只向前移动。在两个指针相遇之前,第一个指针总是位于第二个指针的前面。
// 如果第一个指针指向的数字是偶数而第二个指针指向的数字是奇数,我们就交换这两个数字。
// 顺便复习下宏函数,就不写到文件顶部了
// 能加括号就加括号!!
// 注意不要加;写成语句e.g. {((x)%2)?(false):(true);}
// 要写成表达式
//#define isEven(x) (((x)%2)?false:true)
// 位运算比较快
#define isEven(x) (((x)&1) == 0?true:false)
// 不用中间变量交换两个数,并避免overflow问题
// 异或XOR
// http://blog.youkuaiyun.com/lpt19832003/article/details/5334688
#define mySwap(num1, num2) \
{ \
(num1) = (num1) ^ (num2);\
(num2) = (num2) ^ (num1);\
(num1) = (num1) ^ (num2);\
}
// 将来还可扩展为函数指针,相应的把宏改写为inline 函数
// bool oddEvenSort(int arr[], size_t arrLength, bool (*func)(int))
bool oddEvenSort(int arr[], size_t arrLength)
{
if (arr == NULL || arrLength <=0)
{
return false;
}
int index1 = 0;
int index2 = arrLength - 1;
while(index1 < index2)
{
// 如果index1现在指向奇数,不用交换
if (!isEven(arr[index1]))
{
index1++;
continue;
}
// 如果index2现在指向偶数,不用交换
if (isEven(arr[index2]))
{
index2--;
continue;
}
// 如果index1指向偶数 AND index2指向奇数 交换
mySwap(arr[index1], arr[index2]);
}
return true;
}
1.3 数组中只出现一次的数字[算法]
题目描述:
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。
分析和C++代码:
1.3 数组中只出现一次的数字[算法]
题目描述:
分析和C++代码:
1.3 数组中只出现一次的数字[算法]
题目描述:
分析和C++代码:
1.3 数组中只出现一次的数字[算法]
题目描述:
分析和C++代码:
1.3 数组中只出现一次的数字[算法]
题目描述:
分析和C++代码:
1.3 数组中只出现一次的数字[算法]
题目描述:
分析和C++代码:
1.3 数组中只出现一次的数字[算法]
题目描述:
分析和C++代码:
1.3 数组中只出现一次的数字[算法]
题目描述:
分析和C++代码: