面試準備之常見上機題目蒐羅(一)
1.從考試成績中劃出及格線
(1)及格線是10的倍數
(2)保證至少有60%的學生及格
(3)如果有所有的學生都高於60分,則及格線為60分。
演算法分析:
關鍵資訊點為“保證至少有60%的學生及格”,可將分數線的概念轉換為人數,即只需統計每個檔次的人數,若60以上檔次的人數就是全體人員則分數線為60,否則去尋找(由高分到低分)最先達到60%人數的檔次。
java實現如下:
public class Exam{ public int findPassLine(int[] scores){ int num=scores.length; int[] record=new int[num+1];//記錄每一個檔次的人數 for(int i=0;i<num;i++){ switch(scores[i]/10){ case 10:record[10]++;break; case 9:record[9]++;break; case 8:record[8]++;break; case 7:record[7]++;break; case 6:record[6]++;break; case 5:record[5]++;break; case 4:record[4]++;break; case 3:record[3]++;break; case 2:record[2]++;break; case 1:record[1]++;break; case 0:record[0]++;break; } } int sumh=0;//記錄60分以上所有人數 int suml=0;//記錄60分以下所有人數 for(int j=record.length-1;j>=0;j--){ if(j>=6) sumh+=record[j]; } suml=10-sumh; if(sumh==10){//所有人都在60分以上 System.out.println("所有人的分數均高於60,分數線為:"); return 60; } else{ //有高分檔次向下遍歷 for(int k=record.length-1;k>0;k--){//10~0遍歷 if(record[k]>=6){ return 10*k; } else record[k-1]+=record[k];//向下累加 } } return 0; } public static void main(String[] args){ int a[]={99,89,79,69,0,0,4,5,80,50}; System.out.println(new Exam().findPassLine(a)); int b[]={100,100,100,100,100,80,0,0,0,0}; System.out.println(new Exam().findPassLine(b)); int c[]={100,100,100,100,100,100,0,0,0,0}; System.out.println(new Exam().findPassLine(c)); int d[]={100,100,100,100,100,100,60,80,70,90}; System.out.println(new Exam().findPassLine(d)); } }
輸出:
50
80
100
所有人的分數均高於60,分數線為:
60
2.亮著電燈的盞數
一條長廊裡依次裝有n(1 ≤ n ≤ 65535)盞電燈,從頭到尾編號1、2、3、…n-1、n。每盞電燈由一個拉線開關控制。開始,電燈全部關著。
有n個學生從長廊穿過。第一個學生把號碼凡是1的倍數的電燈的開關拉一下;接著第二個學生把號碼凡是2的倍數的電燈的開關拉一下;接著第三個學生把號碼凡是3的倍數的電燈的開關拉一下;如此繼續下去,最後第n個學生把號碼凡是n的倍數的電燈的開關拉一下。n個學生按此規定走完後,長廊裡電燈有幾盞亮著。
注:電燈數和學生數一致。
演算法分析:無任何演算法可言,只需要按照題目描述實現一邊,不知道有啥捷徑
java實現如下:
//import java.lang.StringBuilder; public class Light{ public int lightNum(int[] lights){ //剛開始預設全部開啟,1開,0閉 int i=1,n=lights.length-1,num=0; while(i<=n){ for(int j=1;j<=n;j++){//遍歷1--n棧燈(0號元素忽略) if(j%i==0){ if(lights[j]==1){ //開著的等被關閉 lights[j]=0; num--; } else if(lights[j]==0) { //關閉的燈被開啟 lights[j]=1; num++; } } } i++;//第i個人 } return num; } //列印亮著的編號 public void printLightsNum(int[] lights){ StringBuilder sb=new StringBuilder(); sb.append("它們分別是:"); for(int i=1;i<=lights.length-1;i++){ if(lights[i]==1){//開著 sb.append(" "); sb.append(i); } } System.out.println(sb.toString()); } public static void main(String[] args){ for(int i=10;i<=100;i+=10){ System.out.println("初始時"+i+"棧燈滅著!"); int[] lights=new int[i+1]; Light obj=new Light(); System.out.println("觸動後還剩下"+obj.lightNum(lights)+"棧燈開著!"); obj.printLightsNum(lights); System.out.println("--------------------------------------------------"); } } }
輸出:
初始時10棧燈滅著!
觸動後還剩下3棧燈開著!
它們分別是: 1 4 9
--------------------------------------------------
初始時20棧燈滅著!
觸動後還剩下4棧燈開著!
它們分別是: 1 4 9 16
--------------------------------------------------
初始時30棧燈滅著!
觸動後還剩下5棧燈開著!
它們分別是: 1 4 9 16 25
--------------------------------------------------
初始時40棧燈滅著!
觸動後還剩下6棧燈開著!
它們分別是: 1 4 9 16 25 36
--------------------------------------------------
初始時50棧燈滅著!
觸動後還剩下7棧燈開著!
它們分別是: 1 4 9 16 25 36 49
--------------------------------------------------
初始時60棧燈滅著!
觸動後還剩下7棧燈開著!
它們分別是: 1 4 9 16 25 36 49
--------------------------------------------------
初始時70棧燈滅著!
觸動後還剩下8棧燈開著!
它們分別是: 1 4 9 16 25 36 49 64
--------------------------------------------------
初始時80棧燈滅著!
觸動後還剩下8棧燈開著!
它們分別是: 1 4 9 16 25 36 49 64
--------------------------------------------------
初始時90棧燈滅著!
觸動後還剩下9棧燈開著!
它們分別是: 1 4 9 16 25 36 49 64 81
--------------------------------------------------
初始時100棧燈滅著!
觸動後還剩下10棧燈開著!
它們分別是: 1 4 9 16 25 36 49 64 81 100
--------------------------------------------------
從輸出中反推原理:最後亮著燈的編號都是可以開方的數,這時為什麼呢?
題中告知所有燈剛開始是關著的,也就說最後想開著,必須觸動開關奇數次,即"該燈所對應的編號數,其公約數有奇數個"。那麼問題就轉化為"什麼樣的數有奇數個公約數",由於已經知道答案了(完全平方數),所有隻好用反證法。
證: 若對任意實數C具有奇數個公約數,且C不是完全平方數
則有C的任意一對公約數m1!=m2,設C有n對公約數,
則C的公約數總數=n*2+2(可以被自身和1整除)=2*(n+1)為偶數
此結論與已知"C具有奇數個公約數"矛盾,故C是完全平方數。
有了上面的結論,即可以直接去找1--n內的完全平方數即可,複雜度就降為O(n)了,我想這就是華為將此題做為中級難度題目的捷徑思路了吧。
3.驗證括號是否匹配
輸入一串字串,其中有普通的字元與括號組成(包括‘(’、‘)’、‘[’,']'),要求驗證括號是否匹配,如果匹配則輸出0、否則輸出1.
Smple input:dfa(sdf)df[dfds(dfd)] Smple outPut:0
演算法分析:利用棧來實現,所有左括號入棧,遇到右括號就進行出棧,看是否匹配。
java實現:
import java.util.Scanner;
import java.util.Stack;
public class Match{
public static void main(String[] args){
Boolean isMatch=true;
Stack<Character> stack=new Stack<Character>();
Scanner s=new Scanner(System.in);
while(true){
char ch=s.nextLine().charAt(0);
if(ch=='q')
break;
else{
switch(ch){
case '{':;
case '[':;
case '(':
stack.push(ch);break;
case '}':
if(stack.empty())
isMatch=false;
else if(stack.pop()!='{')
isMatch=false;
break;
case ']':
if(stack.empty())
isMatch=false;
else if(stack.pop()!='[')
isMatch=false;
break;
case ')':
if(stack.empty())
isMatch=false;
else if(stack.pop()!=')')
isMatch=false;
break;
}
}
}
if(isMatch)
System.out.println("匹配!");
else
System.out.println("不匹配");
}
}
C/C++:
void main()
13.{//子函式宣告
14. void InitStack(SqStack &S);//初始化空棧
15. int StackEmpty(SqStack S);//判空
16. void push(SqStack &S,int e);//進棧
17. void pop(SqStack &S,int &e);//出棧
18. //主函式開始
19. SqStack s;//初始化空棧
20. InitStack(s);
21. char ch[100],*p;int e;
22. p=ch;
23. printf("輸一個含義有()[]{}的括號表示式:\n");
24. gets(ch);
25. while(*p)
26. {
27. switch (*p)
28. {
29. case '{':
30. case '[':
31. case '(': push(s,*p++);break;//只要是左括號就入棧
32. case '}':
33. case ']':
34. case ')':pop(s,e);
35. if ((e=='{' && *p=='}') ||(e=='[' && *p==']') || (e=='(' && *p==')'))
36. p++;
37. else
38. {printf("括號不匹配!");exit(OVERFLOW);}
39. break;
40. default :p++;//其他字元就後移
41. }
42. }
43. if (StackEmpty(s))
44. printf("括號匹配成功");
45. else
46. printf("缺少右括號!");
47. printf("\n");
48.}
4.迴文數
判斷迴文數,是返回1
演算法分析:既然是對稱的,那麼從個位開始,逆序反向生成一個數,若該數與原數相同,則是迴文數。
Scanner s=new Scanner(System.in);
int num=s.nextInt();
int max=num,min=0;
while(max>0){
min=min*10+max%10;//反向生成
max=max/10;//去除最後一位
}
if(min==max)
System.out.println("Yes");
else
System.out.println("No");
附:迴文數還有一個性質,即數字位數與存在的迴文數有如下關係,
1位迴文數: 9個
2位迴文數: 9個
3位迴文數: 90個
4位迴文數: 90個
5位迴文數: 900個
6位迴文數: 900個
…
即每增加兩位,則存在的迴文數為原來的10倍。
5.將整數倒序輸出,剔除重複資料
輸入一個整數,如12336544,或1750,然後從最後一位開始倒過來輸出,最後如果是0,則不輸出,輸出的數字是不帶重複數字的,所以上面的輸出是456321和571。如果是負數,比如輸入-175,輸出-571。
演算法分析:將每一位儲存,儲存時剔除重複元素,而後輸出。(注意符號)
public static void main(String[] args){
Scanner s=new Scanner(System.in);
int num=s.nextInt();
int[] store=new int[]{99,99,99,99,99,99,99,99,99,99,99,99,99};//初始值不要賦個位數,避免和取餘後的數等值
int len=0,tmp=num,last;
while(true){
if(tmp==0)
break;
else{
int lastNum= tmp%10;//取餘求最後一位
tmp=tmp/10;
int flag=1;//待插入陣列中是否含有該數
for(int k=0;k<=len;k++){
if(store[k]==lastNum){
flag=0;//重複則不插入
break;
}
}
if(flag!=0){
store[len]=lastNum;//需要插入
len++;
}
}
}
//len指向待插入位置
if(num<0)
System.out.print("-");
for(int j=0;j<len;j++){
if(store[j]!=0)
System.out.print(Math.abs(store[j]));
}
}
6.大數相減
輸入兩行字串正整數,第一行是被減數,第二行是減數,輸出第一行減去第二行的結果。
備註:1、兩個整數都是正整數,被減數大於減數
示例:
輸入:1000000000000001
1
輸出:1000000000000000
注意大數用char a[] 儲存,用%s接收,一位一位的運算。注意a[0]裡的正負號
演算法描述:一位一位減,最高位無需借位。不僅可以大減小,也可以小減大(大減小取負即可)。
java實現:
public int[] subtraction(int[] a,int[] b){
int[] c=new int[a.length];
//a[0]...a[n]代表高位到低位
for(int i=c.length-1;i>=0;i--){
//最高位不借位
if(i!=0){
if(a[i]<b[i]){
a[i-1]-=1;//向高位借位
a[i]+=10;
}
}
c[i]=a[i]-b[i];//儲存對應位的差值
}
return c;
}
輸出:
2 7 8 7 1 0 0 2 9 4 0 7 0 8 3 3 8 7 0 6
- 2 5 1 3 7 3 8 8 8 3 1 7 5 2 3 7 3 6 1 2
----------------------------------------------------
0 2 7 3 3 6 1 4 1 0 8 9 5 5 9 6 5 0 9 4
0 8 4 9 2 7 2 5 7 8 4 8 1 3 1 0 6 1 7 9
- 2 0 2 1 6 0 4 9 2 8 8 0 6 3 3 0 2 0 5 8
----------------------------------------------------
-1 1 7 2 3 3 2 3 5 0 3 2 5 0 1 9 5 8 7 9
6 6 5 5 5 1 1 1 5 6 5 5 1 6 2 1 9 7 2 9
- 0 2 8 5 9 7 5 8 9 8 2 8 0 1 8 5 7 3 3 4
----------------------------------------------------
6 3 6 9 5 3 5 2 5 8 2 7 1 4 3 6 2 3 9 5
3 4 7 5 7 1 1 1 9 1 9 2 2 0 0 4 5 2 9 8
- 5 9 5 6 1 5 8 9 8 9 7 1 9 7 1 2 5 0 3 5
----------------------------------------------------
-2 4 8 0 4 4 7 7 9 7 7 9 7 7 0 7 9 7 3 7
5 1 9 0 4 6 1 6 1 6 5 3 1 9 9 3 8 5 9 5
- 4 0 2 2 8 3 3 4 8 0 9 0 3 5 5 8 3 1 5 0
----------------------------------------------------
1 1 6 7 6 2 8 1 3 5 6 2 8 4 3 5 5 4 4 5
完整程式碼:
import java.util.Random;
public class Sub{
//判別大小
public Boolean compare(int[] a,int[] b){
Boolean bool=true;//大於
for(int i=0;i<a.length;i++){
//從高位開始遍歷
if(a[i]<b[i]){
bool=false;
break;
}
else if(a[i]>b[i]){
bool=true;
break;
}
}
return bool;
}
public int[] subtraction(int[] a,int[] b){
int[] c=new int[a.length];
//a[0]...a[n]代表高位到低位
for(int i=c.length-1;i>=0;i--){
//最高位不借位
if(i!=0){
if(a[i]<b[i]){
a[i-1]-=1;//向高位借位
a[i]+=10;
}
}
c[i]=a[i]-b[i];//儲存對應位的差值
}
return c;
}
//輸出
public void print(int[] bt){
for(int b : bt){
System.out.print(b+" ");
}
}
public static void main(String[] args){
Random rand=new Random();
for(int i=0;i<5;i++){
Sub sub=new Sub();
int[] a=new int[20];
int[] b=new int[20];
for (int n=0; n<a.length; n++) {
a[n]=rand.nextInt(10);//隨機0--9
b[n]=rand.nextInt(10);
}
System.out.print(" ");
sub.print(a);
System.out.println("");
System.out.print("- ");
sub.print(b);
System.out.println("");
System.out.println("------------------------------------------------");
if(sub.compare(a,b)){//保證被減數大於減數
System.out.print(" ");
sub.print(sub.subtraction(a,b));
System.out.println("");
}
else{
System.out.print(" -");
sub.print(sub.subtraction(b,a));
System.out.println("");
}
System.out.println("");
System.out.println("");
}
}
}
7.上海華為的一道關於指標方面的程式設計題
題目:
int A[nSize],其中隱藏著若干0,其餘非0整數,寫一個函式int Func(int* A, int nSize),使A把0移至後面,非0整數移至 陣列前面並保持有序,返回值為原資料中第一個元素為0的下標。(儘可能不使用輔助空間且考慮效率及異常問題,註釋規範且給出設計思路)
思路:
選擇一個排序演算法對其進行排序,在排序過程中記錄0元素的個數count,即nSize-count為首個0元素的下標;需要注意的是,若排序時需由大到小的排序(題中只說保持有序),不然0元素出現在前半部分又要移動元素。
C實現如下:
#include <stdio.h>
using namespace std;
int Func(int *A,int nSize){
if(A!=0&&nSize>0){
int count=0;//記錄0元素的個數
//折半插入排序
int low,high,mid;
if(*A==0)
count++;
for(int i=1;i<nSize;i++){
low=0;
high=i-1;
mid=(low+high)/2;
while(low<=high){
if(*(A+i)>*(A+mid))//key>mid
high=mid-1;//注意此處故意倒序排列
else
low=mid+1;
mid=(low+high)/2;
}
//high+1為待插入位置
int key=*(A+i);
//後移元素騰出位置
for(int j=i;j>high+1;j--){
*(A+j)=*(A+j-1);
}
*(A+high+1)=key;//插入
if(key==0)
count++;
}
return nSize-count;
}
else
return -1;
}
void main(){
int a[]={0,3,0,4,9,1,0,44,2,0,12};
int index=Func(a,11);
printf("首個0在 %d 處\n",index);
for(int i=0;i<11;i++){
printf("%d ",a[i]);
}
}
輸出:
首個0在 7 處
44 12 9 4 3 2 1 0 0 0 0 請按任意鍵繼續. . .
8.素數問題
題目:
求2~2000的所有素數.有足夠的記憶體,要求儘量快
思路:
查表法,即為2~2000的序列建立對應的表,表大小與序列大小一致(序列需要由小到大排序),選擇最小的素數並將其倍數剔除(在表中記錄),在剩餘的序列中,繼續選擇最小的素數並剔除其倍數,直到剔除到第N個。這樣的好處在於每次遍歷時可以參考上次table中的標記,可以避免許多重複操作。
例如在判斷4是否為素數時,由於在剔除2的倍數時在表中已經標記為NONPRIME(不是素數),那就不比呼叫判斷素數的方法,省去許多操作。
C實現,為了輸出方便,選擇10以內的素數
#include <stdio.h>
#include <math.h>
#define TRUE 1
#define FALSE 0
#define NULL -1 //未遍歷標記
#define NONPRIME 0//不是素數標記
#define PRIME 1 //是素數標記
#define LEN 10+1 //為了讓陣列下標一致
using namespace std;
int isPrime(int num){
if(num==2)
return TRUE;
for(int i=2;i<=sqrt((double)num);i++){
if(num%i==0)
return FALSE;
}
return TRUE;
}
//將num的倍數剔除(num為最小質數)
void deleNonPrime(int table[], int num){
table[num]=PRIME;
for(int i=2*num;i<LEN;i+=num){
if(table[i]==NULL){//有可能已經被賦值了
table[i]=NONPRIME;
}
}
}
void print(int arr[],int size){
for(int i=2;i<size;i++){
printf("%d ",arr[i]);
}
printf("\n");
}
void main(){
int primes[LEN]={NULL};
int table[LEN]={NULL};//建立對應的表
for(int i=2;i<LEN;i++){
primes[i]=i;
table[i]=NULL;
}
for(int j=2;j<LEN;j++){
if(j==2){
deleNonPrime(table,2);
}
else{//參考上次表中的標記
if(table[j]==NULL){//有可能為素數(剔除時有可能已經判斷過了,避免重複判斷)
if(isPrime(primes[j])){
deleNonPrime(table,primes[j]);
}
}
}
printf("序列:");
print(primes,LEN);
printf(" 表:");
print(table,LEN);
printf("\n\n");
}
for(int i=2;i<LEN;i++){
if(table[i]==PRIME)
printf("%d ",i);
}
}
輸出:
序列:2 3 4 5 6 7 8 9 10
表:1 -1 0 -1 0 -1 0 -1 0
序列:2 3 4 5 6 7 8 9 10
表:1 1 0 -1 0 -1 0 0 0
序列:2 3 4 5 6 7 8 9 10
表:1 1 0 -1 0 -1 0 0 0
序列:2 3 4 5 6 7 8 9 10
表:1 1 0 1 0 -1 0 0 0
序列:2 3 4 5 6 7 8 9 10
表:1 1 0 1 0 -1 0 0 0
序列:2 3 4 5 6 7 8 9 10
表:1 1 0 1 0 1 0 0 0
序列:2 3 4 5 6 7 8 9 10
表:1 1 0 1 0 1 0 0 0
序列:2 3 4 5 6 7 8 9 10
表:1 1 0 1 0 1 0 0 0
序列:2 3 4 5 6 7 8 9 10
表:1 1 0 1 0 1 0 0 0
2 3 5 7 請按任意鍵繼續. . .
注意isPrime函式判斷素數時只用判斷至sqrt處(素數定理)。
9.作業系統任務排程問題
題目:
作業系統任務分為系統任務和使用者任務兩種。其中,系統任務的優先順序 < 50,使用者任務的優先順序 >= 50且 <= 255。優 先級大於255的為非法任務,應予以剔除。現有一任務佇列task[],長度為n,task中的元素值表示任務的優先順序,數值越小,優先順序越高。函式scheduler 實現如下功能,將task[] 中的任務按照系統任務、使用者任務依次存放到 system_task[] 陣列和 user_task[] 陣列中(陣列中元素的值是任務在task[]
數 組中的下標),並且優先順序高的任務排在前面,陣列元素為-1表示結束。
例如:
task[] = {0, 30, 155, 1, 80, 300, 170, 40, 99}
system_task[] = {0, 3, 1, 7, -1}
user_task[] = {4, 8, 2, 6, -1}
函式介面 void scheduler(int task[], int n, int system_task[], int user_task[])
思路:
先以50做為關鍵字對原有序列進行一次快排,返回50的待插入位置location即為系統任務的個數,然後以location做為分界線,左右兩邊分別進行快排,最後依次將左半部放在system_task[]中,右半部分放在user_task[](需剔除大於255的)
C/C++實現如下:
#include <stdio.h>
using namespace std;
// 利用一趟快速排序找分界線的位置i,即[low,i)為系統任務,[i,high]為使用者任務
int findLine(int task[],int lowSpace,int highSpace,int key){
int low=lowSpace,high=highSpace;
while(low<high){
while(low<high&&task[high]>key){
high--;
}
if(low<high){
int tmp=task[high];
task[high]=task[low];
task[low]=tmp;
}
while(low<high&&task[low]<key){
low++;
}
if(low<high){
int tmp=task[low];
task[low]=task[high];
task[high]=tmp;
}
}
return low;
}
void quickSort(int subTask[],int lowSpace,int highSpace){
if(lowSpace<highSpace){//限制遞迴
int low=lowSpace,high=highSpace;
int insertIndex;//待插入位置
int key=subTask[lowSpace];//關鍵字
while(low<high){
while(low<high&&subTask[high]>=key){
high--;
}
if(low<high){
int tmp=subTask[high];
subTask[high]=subTask[low];
subTask[low]=tmp;
}
while(low<high&&subTask[low]<=key){
low++;
}
if(low<high){
int tmp=subTask[low];
subTask[low]=subTask[high];
subTask[high]=tmp;
}
}
insertIndex=low;
subTask[insertIndex]=key;
if(insertIndex==lowSpace)
quickSort(subTask,insertIndex+1,highSpace);//只用排高區
else if(insertIndex==highSpace)
quickSort(subTask,lowSpace,insertIndex-1);//只用排低區
else {
quickSort(subTask,lowSpace,insertIndex-1);
quickSort(subTask,insertIndex+1,highSpace);
}
}
}
void scheduler(int task[], int n, int system_task[], int user_task[]){
int index=findLine(task,0,n-1,50);//以50為關鍵字劃分
//分別排序
quickSort(task,0,index);
quickSort(task,index+1,n-1);
int len=0;//記錄使用者任務的長度,因為需要剔除大於255的數,所以長度不一定為n-index
for(int i=0;i<n;i++){
//系統任務[0,index)
if(i<=index){
system_task[i]=i;
}
//使用者任務[index,n)
else if(i>index){
//剔除無效任務
if(task[i]>=50&&task[i]<=255){
user_task[i-index-1]=i;
len++;
}
}
}
system_task[index+1]=-1;//結束
user_task[len]=-1;
}
void printArr(int task[],int n){
for(int i=0;i<n;i++){
printf("%d ",task[i]);
}
printf("\n");
}
//測試
void main(){
int task[]={0, 30, 155, 1, 80, 300, 170, 40, 99};
int system_task[9]={-1};
int user_task[9]={-1};
scheduler(task,9,system_task,user_task);
printf("排序完成後總任務為:\n");
printArr(task,9);
printf("系統任務為:\n");
printArr(system_task,9);
printf("使用者任務為:\n");
printArr(user_task,9);
}
輸出:
排序完成後總任務為:
0 1 30 40 80 99 155 170 300
系統任務為:
0 1 2 3 -1 0 0 0 0
使用者任務為:
4 5 6 7 -1 0 0 0 0
請按任意鍵繼續. . .
突然發現自己把題意弄錯了,我雖然實現了任務分離和任務,但是題目輸出的是原始索引座標,並不是排序後的。為了實現尋找原始索引,引入一個索引表,只要任務元素被移動,則table的索引隨之移動,最後只要查表即可。
C#實現如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace 控制檯程式設計練習
{
class 任務分配
{
//尋找關鍵字的分界線
int findLine(int[] task,int lowSpace,int highSpace,int key,int[] table){
int low=lowSpace,high=highSpace;
while(low<high){
while(low<high&&task[high]>key){
high--;
}
if(low<high){
swap(high, low, task);
swap(high, low, table);
}
while(low<high&&task[low]<key){
low++;
}
if(low<high){
swap( low,high ,task);
swap(low, high, table);
}
}
return low;
}
//交換
void swap(int a,int b,int[] task){
int tmp= task[a];
task[a]=task[b];
task[b]=tmp;
}
//快排
void quickSort(int[] subTask,int lowSpace,int highSpace,int[] index){
if(lowSpace<highSpace){//限制遞迴
int low=lowSpace,high=highSpace;
int insertIndex;//待插入位置
int key=subTask[lowSpace];//關鍵字
int table_key = index[lowSpace];//表索引虛擬關鍵字
while(low<high){
while(low<high&&subTask[high]>=key){
high--;
}
if(low<high){
swap(high,low,subTask);
swap(high,low,index);
}
while(low<high&&subTask[low]<=key){
low++;
}
if(low<high){
swap(low,high,subTask);
swap(low,high,index);
}
}
insertIndex=low;
subTask[insertIndex]=key;
index[insertIndex]=table_key;//索引表也要變動
if(insertIndex==lowSpace)
quickSort(subTask,insertIndex+1,highSpace,index);//只用排高區
else if(insertIndex==highSpace)
quickSort(subTask,lowSpace,insertIndex-1,index);//只用排低區
else {
quickSort(subTask,lowSpace,insertIndex-1,index);
quickSort(subTask,insertIndex+1,highSpace,index);
}
}
}
//建立索引表
int[] creatTable(int n)
{
int[] table = new int[n];
for (int i = 0; i < n; i++)
{
table[i] = i;
}
return table;
}
void scheduler(int[] task, int n, int[] system_task, int[] user_task){
int[] table = creatTable(n);
int index = findLine(task, 0, n - 1, 50, table);//以50為關鍵字劃分
//分別排序
quickSort(task,0,index,table);
quickSort(task,index+1,n-1,table);
int len=0;//記錄使用者任務的長度,因為需要剔除大於255的數,所以長度不一定為n-index
for(int i=0;i<n;i++){
//系統任務[0,index)
if(i<=index){
system_task[i]=table[i];
}
//使用者任務[index,n)
else if(i>index){
//剔除無效任務
if(task[i]>=50&&task[i]<=255){
user_task[i-index-1]=table[i];
len++;
}
}
}
system_task[index+1]=-1;//結束
user_task[len]=-1;
}
void printArr(int[] task,int n){
for(int i=0;i<n;i++){
Console.Write(task[i]+" ");
}
Console.WriteLine();
}
static void Main()
{
任務分配 s = new 任務分配();
int[] task={0, 30, 155, 1, 80, 300, 170, 40, 99};
int[] system_task=new int[9];
int[] user_task=new int[9];
Console.WriteLine("原始任務為:");
s.printArr(task,9);
s.scheduler(task, 9, system_task, user_task);
Console.WriteLine("系統任務為:");
s.printArr(system_task, 9);
Console.WriteLine("使用者任務為:");
s.printArr(user_task, 9);
}
}
}
輸出:
原始任務為:
0 30 155 1 80 300 170 40 99
系統任務為:
0 3 1 7 -1 0 0 0 0
使用者任務為:
4 8 2 6 -1 0 0 0 0
請按任意鍵繼續. . .
10.奇偶插入排序
題目:
對一個數組,將陣列中偶數從大到小排序,奇數從小到大排序,奇數和偶數交叉著放且輸出陣列第一位放奇數若奇數和偶數不等長,則把剩下的直接放到陣列中。
思路:
將奇數和偶數元素分別存放,然後分別排序,最後一起交叉填充(覆蓋)到原陣列。
C/C++實現如下:
#include<stdio.h>
#include<malloc.h>
#define DEFAULT 0
#define low_to_high 0//由小到大
#define high_to_low 1//由大到小
using namespace std;
//折半插入排序
void halfSort(int *a,int n,int type){
for(int i=1;i<n;i++){
int high=i-1;
int low=0;
int mid=(high+low)/2;
int key=a[i];//待排關鍵字
//尋找位置
if(type==low_to_high){
while(low<=high){
if(a[mid]<key)
low=mid+1;
else
high=mid-1;
mid=(low+high)/2;
}
}
else{
while(low<=high){
if(a[mid]<key)
high=mid-1;
else
low=mid+1;
mid=(low+high)/2;
}
}
//插入位置在high+1,全體移動a[high+1]...a[i]
for(int j=i;j>high+1;j--){
a[j]=a[j-1];
}
a[high+1]=key;
}
}
void print(int *a,int n){
for(int i=0;i<n;i++){
printf("%d ",*(a+i));
}
/*while(*a!='\0'){
printf("%d ",*a++);
}*/
printf("\n");
}
void oddAndEvenSort(int a[],int n){
int odd[10]={0};
int even[10]={0};
int evenCount=0;//偶數個數
int oddCount=0;
for(int i=0;i<n;i++){
if(a[i]%2==0){
even[evenCount]=a[i];
evenCount++;
}
else{
odd[oddCount]=a[i];
oddCount++;
}
}
halfSort(odd,oddCount,low_to_high);
halfSort(even,evenCount,high_to_low);
if(oddCount==0){
print(even,evenCount);
}
else if(evenCount==0){
print(odd,oddCount);
}
else if(oddCount<evenCount){
for(int i=0;i<oddCount;i++){
a[2*i]=odd[i];
a[2*i+1]=even[i];
}
for(int j=oddCount;j<n;j++){//剩餘偶數補全
a[j+oddCount]=even[j];
}
print(a,n);
}
else if(oddCount==evenCount){
for(int i=0;i<oddCount;i++){
a[2*i]=odd[i];
a[2*i+1]=even[i];
}
print(a,n);
}
else if(oddCount>evenCount){
for(int i=0;i<evenCount;i++){
a[2*i]=odd[i];
a[2*i+1]=even[i];
}
for(int j=evenCount;j<n;j++){//剩餘奇數補全
a[j+evenCount]=odd[j];
}
print(a,n);
}
}
void main(){
int a1[]={2,4,6,8,10,12,14,16,18,1};
oddAndEvenSort(a1,10);
int a2[]={2,4,6,8,10,1,3,5,7,9};
oddAndEvenSort(a2,10);
int a3[]={2,4,6,1,3,5,7,9,11,13};
oddAndEvenSort(a3,10);
}
輸出:
1 18 16 14 12 10 8 6 4 2
1 10 3 8 5 6 7 4 9 2
1 6 3 4 5 2 7 9 11 13
總結:又沒仔細看題,偶數元素是從大到小,奇數是從小到大排序,題目雖簡,但也須仔細認真,切記。
相關推薦
面試準備之常見上機題目蒐羅(一)
1.從考試成績中劃出及格線 (1)及格線是10的倍數 (2)保證至少有60%的學生及格 (3)如果有所有的學生都高於60分,則及格線為60分。 演算法分析: 關鍵資訊點為“保證至少有60%的學生及格”,可將分數線的概念轉換為人數,即只需統計每個檔次的人數,若60以
Centos之常見目錄作用介紹(九)
wal har g++ init tco 文檔 http 臨時 哪些 我們先切換到系統根目錄 / 看看根目錄下有哪些目錄 [[email protected]/* */ ~]# cd / [[email protected]/* */ /]# ls
【JAVA秒會技術之秒殺面試官】JavaEE常見面試題(一)
parameter 和數 程序 配置 except 查詢 解析 list 就會 1.Struts2中,Action通過什麽方式獲取用戶從頁面輸入的數據,又是通過什麽方法把數據傳給視圖層顯示的? 答:(1)Action從頁面獲取數據的方式有三種: ①通過Act
Java面試2018常考題目彙總(一)
因為最近在忙著找工作,看到了很多面試整理的文章,於是便有了自己也寫一篇,部分原創,大部分是我四處蒐集的,我想整理一份最全最新的文章,方便大家總結!廢話不多說,開始! 一、JAVA基礎篇-概念 1.簡述你所知道的Linux: Linux起源於1991年
前端面試題目總結(一)
1.判斷下面輸出內容,並嘗試怎樣正確輸出0,1,2,3,4,5 for (var i = 0; i <= 5; i++) { setTimeout(function timer(){ console.log(i) }, i * 1000) } /
【JAVA秒會技術之秒殺面試官】JavaSE常見面試題(一)
【前言】別人都在你看不到的地方暗自努力,在你看得到的地方,他們也和你一樣顯得遊手好閒,和你一樣會抱怨,而只有你自己相信這些都是真的,最後,也只有你一個人繼續不思進取 …… 【下載】本人剛學習Java時總結的一些JavaSE常見面試題,偶爾在電腦中翻出,重新整理一下
HTML5面試題目彙總(一)
2、行內元素有哪些?塊級元素有哪些? 空(void)元素有那些?答案解析:行內元素:a b span img input select strong 塊級元素:div ul ol li dl dt dd h1 h2 h3 h4 p 等 空元素:<br> <
項目進階 之 集群環境搭建(一)概述
問題 特點 多臺 cpu 好的 content 成了 系統資源 通過 今天我們說一個不是特別新,但近期今年伴隨大數據熱而比較火的一個技術-集群技術。 什麽是集群技術 集群(Cluster)技術是指一組相互犭蟲立的計算機,利用快速通信網絡組
Centos 7.0 編譯安裝LAMP(Linxu+apache+mysql+php)之源碼安裝Apache (一)
mysql apache mysql編譯安裝 apache編譯安裝 lamp編譯安裝 Apache 簡介: Apache是世界使用排名第一的Web服務器軟件。它可以運行在幾乎所有廣泛使用的計算機平臺上,由於其跨平臺和安全性被廣泛使用,是最流行的Web服務器端軟件之一。它快速、可靠
Java之面向對象例子(一)
顯示 人類 運算 例子 ble person 成員變量 年月日 pub 定義一個人類,給這個類定義一個從身份證獲取生日的方法,輸入身份證,獲取出生年月日 //主方法 package com.hanqi.maya.model; import java.util.Scanne
haproxy高可用之非搶占keepalived(一)
haproxy keepalivedHAProxy簡介HAProxy是免費、極速且可靠的用於為TCP和基於HTTP應用程序提供高可用、負載均衡和代理服務的解決方案,尤其適用於高負載且需要持久連接或7層處理機制的web站點。HAProxy還可以將後端的服務器與網絡隔離,起到保護後端服務器的作用。HAProxy的
react入門之使用webpack搭配環境(一)
ges 名稱 更新 2.0 ref gin 分配 res body react入門之搭配環境(一) 如果你想直接上手開發,而跳過這些搭配環境的繁瑣過程,推薦你使用官方的create-react-app命令 npm install -g create-react-app
機器學習之SVM初解與淺析(一):最大距離
機器學習 svm 最大距離 2 / ||w|| 這段時間在看周誌華大佬的《機器學習》,在看書的過程中,有時候會搜搜其他人寫的文章,對比來講,周教授講的內容還是比較深刻的,但是前幾天看到SVM這一章的時候,感覺甚是晦澀啊,第一感覺就是比較抽象,特別是對於像本人這種I
機器學習之SVM初解與淺析(一):
機器學習 svm 最大距離 2 / ||w||sdsshngshan‘gccha 這段時間在看周誌華大佬的《機器學習》,在看書的過程中,有時候會搜搜其他人寫的文章,對比來講,周教授講的內容還是比較深刻的,但是前幾天看到SVM這一章的時候,感覺甚是晦澀啊,第一感覺就
C# ABP源碼詳解 之 BackgroundJob,後臺工作(一)
技術分享 轉發 cbac wid 性能 更新 strong ron bst 本文歸屬作者所有,轉發請註明本文鏈接。 1. 前言 ABP的BackgroundJob,用來處理耗時的操作。比如客戶端上傳文件,我們要把文件(Excel)做處理,這耗時的操作我們應該放到後臺工作
【java】java學習之路-01-Linux基礎(一)
x文件 字母 at命令 超過 用戶登錄 創建刪除 軟連接 nbsp tail linux學習方法: 你的程序要在服務器(linux)上執行,服務器沒有桌面系統,學習linux就是學習命令。 一、Linux介紹 1、芬蘭大學生,名字叫Linux,因為個人興趣,編寫了一個類Un
機器學習之支持向量機(一):支持向量機的公式推導
根據 監督式 art 通用 利用 哪些 這就是 在線 方法 註:關於支持向量機系列文章是借鑒大神的神作,加以自己的理解寫成的;若對原作者有損請告知,我會及時處理。轉載請標明來源。 序: 我在支持向量機系列中主要講支持向量機的公式推導,第一部分講到推出拉格朗日對偶函數的對偶因
LeetCode題目總結(一)
括號匹配 比較 最長 github上 三種 https 就是 最長回文 符號 我的代碼在github上,https://github.com/WINTERFELLS/LeetCode-Answers 這裏只提供個人的解題思路,不一定是最好的。 Problems1-20 尋
硬件系列之超聲波模塊介紹(一)
返回 精度 就是 包括 發送 平時 自動 距離 c-s HC-SR04模塊可提供2cm-40cm的非接觸式距離感測功能,測距精度可達3mm: 模塊包括超聲波發生器,接收器與控制器,檢測角度30度。 控制方式: 采用IO口TRIG觸發測距,給最少10us的高電平信號 模塊自動
網絡駭客入門之網絡編程(一):網絡應知應會
網絡網絡駭客入門之網絡編程(一):網絡應知應會一、計算機網絡在設計之初就決定了它結構簡單,傳輸可靠的特點,除此之外,它還能連接不同種類的計算機在網絡上,各個節點同等重要且必須有冗余路由二、網絡在理論上被分為七層,從下到上,物理層,數據鏈路層,網絡層,傳輸層,會話層,表示層,應用層在實際的應用上分為四層,即:鏈