对于数组中数字的各种操作引发的笔试题目也是各种各样。本篇文章就对数组中和数字相关的笔试算法题目进行总结。
一:编程之美 求一个数组能组成的最大的数
给定只包含正数的数组,给出一个方法,将数组中的数拼接起来,得到的数,是最大的。 例如: [4, 94, 9, 14, 1] 拼接之后,所得最大数为:9944141
思路其实很简单,就是按照数的大小排序,大的排到高位,小的排到低位,然后依次输出排好序的数字,这个时候最后的结果肯定是最大的。比如对于数组[1,2,3,4,5],从大到小排序后结果为[5,4,3,2,1],所以最后可以组成的最大结果就是54321。
但是,上面数组中所有元素的位数都是相同的,都是一位。当遇到位数不同的时候就需要稍微额外处理一下。比如第一个数组中的9,94两个数字,那谁应该排在前面那。遇到这种情况就使用虚拟填充的做法,填充到两个两个数的位数相同,然后再做比较。对于9,94来说,因为9只有一位,而94是两位,那么就把9填充为99,这个时候比较99与94的大小,结果就是实际数字9,94的大小了。在填充的时候,填充的数字为位数少的数字的本身。还是上面数组对于14与1比较,最后填充后的结果就是14与11的比较,可以看出14大于11,所以14要排在1的前面。
#include <stdio.h>
#include <stdlib.h>
/*
Name:
Copyright:
Author:
Date: 20/07/13 11:51
Description: 数组中的数拼接起来,得到的数是最大
*/
int comp(const void *first, const void *second){
int a = *(int *) first;
int b = *(int *) second;
char a_str[3];
char b_str[3];
itoa(a, a_str, 10);
itoa(b, b_str, 10);
if(a_str[0] == b_str[0]){
//进行虚拟填充,每次比较位数少那个数字的第一位 ,我默认数组每个元素最大为三位数
for(int i = 1; i < 3; i ++){
if(a_str[1] > b_str[1]){
if(b_str[1] != ' '){
return true;
}else{
if(a_str[1] > b_str[0]){
return true;
}
return false;
}
return false;
}else{
if(a_str[1] != ' '){
return true;
}else{
if(a_str[0] > b_str[1]){
return true;
}
return false;
}
}
}
}else{
if(a_str[0] > b_str[0]){
return true;
}
return false;
}
}
void sortArray(int *array, int length){
for(int i = length - 1; i >= 0; i --){
printf("%d ", array[i]);
}
printf("\n");
qsort(array, length, sizeof(int), comp);
for(int i = length - 1; i >= 0; i --){
printf("%d", array[i]);
}
}
void max(int *array, const int length){
if(array == 0){
return;
}
sortArray(array, length);
}
main(){
int array[] = {4, 94, 9, 14, 1};
max(array, 5);
system("pause");
}
二:编程之美 求一个数组最大和(微软笔试题目)
这个题目应该还是比较经典的,很多公司都考试过。题目大意是给出一个数组,让你求该数组能组成的最大的和是多少,并打印出组成最大和的子数组。
该题目可以利用暴力法,两个for循环嵌套,挨个寻找最大的值,这是O(n^2)的复杂度。优化后的算法是利用动态规划的思想进行求和计算。
主要思想就是声明最大和sum为0,从末尾朝前开始遍历,并挨个相加。对于相加后的值tmp与sum比较,如果大于sum则更新sum的值;如果小于sum但是大于0,则tmp保持不变继续朝前遍历;如果小于sum而且小于0,那么tmp置0,sum不变,继续朝前遍历。算法结束
三:编程之美 求两个数组的和为某个数值(微软笔试题目)
解法1:肯定是可以通过暴力去两次遍历解决的。第一层遍历选择一个数,第二层遍历看当前的数值和外层循环的数值的和是否为给定值。复杂度为n^2。
解法2:可以先通过排序,让数组变成有序的,然后外层一个for循环获取一数值current,通过result = sum-current得到另一个值,然后通过二分查找检查数组中是否含有result。复杂度为n*logN
四:编程之美 求三个数的和为某个数组(雅虎笔试题目)
这个题目是今年的雅虎笔试题目。意思是给出两个数组A,B,让你在某个数组中找出一个,另一个数组中找出者两个,让三个数值的和为给定的sum值。
其实这个题目可以拆分成两个过程:
第一步在数组A中选择一个数值current,然后result = sum - current,再去数组B中检查是否有两个值的和为result,这就回到了上一个题目
第二步在数组B中选择一个数字,和第一步做相同的操作。
复杂度为n^2*logN。针对此题目有好的想法,还请提出。
五:编程之美 求一个N个元素的数组中N-1个的最大乘积。
算法思想是优先求出数组中所有值的乘积,然后根据乘积的不同情况进行不同分析。对于所有数的乘积,其结果只有三种情况大于0、等于0和小于0。所以我们也可以针对这三种情况做不同的分析。
#include <iostream>
#include <stdlib.h>
#include <limits>
using namespace std;
const int LENGTH = 10;
int max1(const int array[]){
int sum = 1;
for(int i = 0;i < LENGTH; i++){
sum = sum * array[i];
}
if(sum == 0){
int zero_num = 0;
for(int i = 0;i < LENGTH; i++){
if(array[i] == 0) {
zero_num ++;
}
}
if(zero_num >1){
sum = 0;
}else{
sum = 1;
for(int i = 0; i < LENGTH; i++){
if(array[i] != 0) {
sum = sum * array[i];
}
}
if(sum < 0) sum = 0;
}
}else if(sum < 0){
int min = INT_MAX;
for(int i = 0;i < LENGTH; i++){
if(abs(array[i]) <= min){
min = array[i];
}
}
sum = sum / min;
}else{
int min = INT_MAX, max = 0;
for(int i = 0;i < LENGTH; i++){
if(array[i] >0 && array[i] <= min){
min = array[i];
}
if(abs(array[i]) > max){
max = array[i];
}
}
if(min == INT_MAX){
sum = sum / max;
}else{
sum = sum / min;
}
}
return sum;
}
main(){
int array[LENGTH];
for(int i = 0;i < LENGTH; i++){
cin >> array[i];
}
for(int i = 0;i < LENGTH; i++){
cout << array[i] << " ";
}
int max = max1(array);
cout << endl;
cout << "max:" << max;
system("pause");
}