昨晚剛剛寫的幾道算法題,難度也還行,就是所有AC有些困難,當時第一題AC、第二題AC 60%,第四題AC 40%,第五題沒有時間寫完了,這個應該所有AC了;其中第三題沒有寫出來html
某個國家的電話號碼規範爲:①以8開頭;②長度爲11位java
如今給出任意長度的一串數字,判斷是否能夠經過從頭部或者尾部連續刪除得到一串符合規範的電話號碼?程序員
下面的代碼是我第一次就寫好的、後期沒有優化的,感受也沒什麼能夠優化的空間了【使用subString還能夠在縮小搜索範圍】,這個題目一次經過算法
package com.cnblogs.mufasa.Main1; import java.util.Scanner; public class Main { public static void main(String[] args) { //0,測試 //1,輸入 Scanner sc=new Scanner(System.in); int t=sc.nextInt(); for(int i=0;i<t;i++){ sc.next(); String str=sc.next(); int loc=str.indexOf("8"); if(loc!=-1&&str.length()-loc>=11){ System.out.println("YES"); }else{ System.out.println("NO"); } } //2,處理 //3,輸出 } } /* 4 8 8888888888888 8 18111111 13 18111111111111 10 11118111111 */
有M個程序員【M爲偶數】,每一個程序員的拖延症拖延時間爲Ti,同時有M/2個編程任務,每一個編程任務須要兩個程序一塊兒解決,先求解所有任務的最小拖延耽誤時間是多少?【兩個程序員拖延時間相加爲每一個任務的拖延時間】編程
個人第一次解答編程爲:【在原有基礎上,本身思考了一些測試用例檢查出來沒有所有AC的部分緣由】數組
package com.cnblogs.mufasa.Main2_1; import java.util.Arrays; import java.util.Scanner; class Node implements Comparable<Node>{ int num; int time; public Node(int num,int time){ this.num=num; this.time=time; } @Override public int compareTo(Node o) { return time-o.time; } } public class Main { public static void main(String[] args) { //0,測試 //1,輸入 Scanner sc=new Scanner(System.in); int n=sc.nextInt(); Node[] arr=new Node[n]; for(int i=0;i<n;i++){ int num=sc.nextInt(); int time=sc.nextInt(); arr[i]=new Node(num,time); } //2.1,處理 Arrays.sort(arr); //2.2,處理 int x=0,y=n-1,maxTime=0; while (x!=y&&x+1!=y){ if(arr[x].time+arr[y].time>maxTime){ maxTime=arr[x].time+arr[y].time; } if(arr[x].num>arr[y].num){ y--; arr[x].num-=arr[y].num; }else if(arr[x].num<arr[y].num){ x++; arr[y].num-=arr[x].num; }else { x++; y--; } } if(arr[x].time+arr[y].time>maxTime){ maxTime=arr[x].time+arr[y].time; } //3,輸出 System.out.println(maxTime); } } /* M名員工,第i名員工有拖延時間ti 有M/2分工做須要完成,每份工做須要安排2名員工 測試用例1:AC 30% 3 1 8 2 6 1 2 測試用例2:這個第一次沒有經過,光標判斷不完善致使 4 1 8 1 5 1 2 1 6 測試用例3:測試經過 4 3 8 1 5 1 2 1 6 */
題目: 將一個數組分紅兩部分,不要求兩部分所包含的元素個數相等,要求使得這兩個部分的和的差值最小。好比對於數組{1,0,1,7,2,4},能夠分紅{1,0,1,2,4}和{7},使得這兩部分的差值最小。ide
這個我當時沒有思路【其實有一個遍歷的思路,可是他們題目的輸入範圍大小一看就知道這種方法是不行的】測試
思路:差最小就是說兩部分的和最接近,並且和全部數的和SUM的一半也是最接近的。假設用sum1表示第一部分的和,sum2表示第二部分的和,SUM表示全部數的和,那麼sum1+sum2=SUM。假設sum1<sum2 那麼SUM/2-sum1 = sum2-SUM/2;
因此咱們就有目標了,使得sum1<=SUM/2的條件下儘量的大。也就是說從n個數中選出某些數,使得這些數的和儘量的接近或者等於全部數的和的通常。這其實就是簡單的揹包問題了:
揹包容量是SUM/2. 每一個物體的體積是數的大小,而後儘量的裝滿揹包。
dp方程:f[i][V] = max(f[i-1][V-v[i]]+v[i], f[i-1][V] )
f[i][V]表示用前i個物體裝容量爲V的揹包可以裝下的最大值,f[i-1][V-v[i]]+v[i]表示第i個物體裝進揹包的狀況,f[i-1][V]表示第i件物品不裝進揹包的狀況。 優化
dp動態規劃求解,空間複雜度較高,變成了一個揹包問題this
package com.cnblogs.mufasa.Main3.Demo; import java.util.Arrays; public class Dp_backpack { public static void match(int[] arr){ int sum = Arrays.stream(arr).sum(); int len = arr.length; int halfOfSum = sum/2; int matrix_firstDimensionLen = len+1; int matrix_secondDimensionLen = halfOfSum+1; int[][] matrix = new int[matrix_firstDimensionLen][matrix_secondDimensionLen]; for (int i = 1; i < matrix_firstDimensionLen; i++) { for (int j = 1; j < matrix_secondDimensionLen; j++) { //若是第i件物體不裝進揹包 matrix[i][j] = matrix[i-1][j]; //若是第i件物體裝進揹包 //備註:j - arr[i-1] >= 0防止下標爲負 if(j - arr[i-1] >= 0 && matrix[i - 1][j - arr[i-1]] + arr[i-1] > matrix[i][j]){ matrix[i][j] = matrix[i - 1][j - arr[i-1]] + arr[i-1]; } } } System.out.print(matrix[len][halfOfSum]+"\t"); System.out.println(sum-matrix[len][halfOfSum]); } public static void main(String[] args){ int[] arr = {1,2,3,4,5}; match(arr); } }
參考連接:
https://blog.csdn.net/baidu_37107022/article/details/73123817
http://www.javashuo.com/article/p-ekfhpurs-bo.html
有一組無序的正整數數組,每次輸出其最小的正整數,其餘全部數字減去這個數,若是全部的數據都爲0或者負數,那麼直接輸出0,這個過程進行k輪
個人思路是先進行由小到大的排序,以後從頭至尾進行逐項判斷輸出,而且更新當前須要減去的數值大小!,時間複雜度爲O(logn+k)
package com.cnblogs.mufasa.Main4; import java.util.Arrays; import java.util.Scanner; public class Main { public static void main(String[] args) { //0,測試 //1,輸入 Scanner sc=new Scanner(System.in); int n=sc.nextInt(); int k=sc.nextInt(); int[] arr=new int[n]; for(int i=0;i<n;i++){ arr[i]=sc.nextInt(); } //2,處理 Arrays.sort(arr); int preNum=0; boolean flag=false; int loc=0; for(int i=0;i<k;i++){ if(loc>=n){ System.out.println(0); }else { int temp=arr[loc]-preNum; if(temp<=0){//須要跳到下一個位置 loc=SinNext(arr,preNum,loc+1); }else {//不小於零 System.out.println(temp); preNum+=temp; loc++; } } } //3,輸出 } private static int SinNext(int[] arr,int preNum,int loc){//遞歸調用這裏 if(loc>arr.length-1){//直接輸出0 System.out.println(0); return arr.length; }else { int temp=arr[loc]-preNum; if(temp<=0){//須要跳到下一個位置 loc=SinNext(arr,preNum,loc+1); }else {//不小於零 System.out.println(temp); preNum+=temp; loc++; } } return loc; } } /* 7 5 5 8 10 3 6 10 8 5 5 1 1 1 1 1 4 5 3 1 3 5 */
有兩組正整數數組,他們對方都在各個任取一個相加組成新的數組的內容,例如:
1 2 1 0 0
1 2 3 0 0
你那麼新數組就有5*5=25個元素
將這25個元素所有互相取異或將最後結果輸出。這裏須要用到數學相關的知識:①異或;②異或;③異或;
兩個相同的數值異或爲0;0與任何數值異或爲這個數值自己;
例如:
①5^5=0;123^123=0;
②0^1=1;0^15632=15632;
因此咱們只要判斷出結果中奇數個的數值,將他們異或一次便可得出正確結果;
而且原始兩個數組中偶數倍出現的數值能夠直接忽略掉,由於偶數倍出現的數值和另一組數據的任何數值相加也都是相同數值偶數倍出現,那麼異或以後一定爲0;
關於算法複雜度的問題:其實還好,首先使用的不是窮舉法;其次將冗餘的一些計算直接掐掉了;算法複雜度大體爲O((logn)^2)
package com.cnblogs.mufasa.Main5; import java.util.*; public class Main { public static void main(String[] args) { //0,測試 //1,輸入 Scanner sc=new Scanner(System.in); int n=sc.nextInt(); TreeMap<Integer,Integer> tm1=new TreeMap<>(); TreeMap<Integer,Integer> tm2=new TreeMap<>(); //2,處理 for(int i=0;i<n;i++){ int temp=sc.nextInt(); Object num=tm1.get(temp); if(num!=null){ tm1.put(temp,((int) num)+1); }else { tm1.put(temp,1); } } for(int i=0;i<n;i++){ int temp=sc.nextInt(); Object num=tm2.get(temp); if(num!=null){ tm2.put(temp,((int) num)+1); }else { tm2.put(temp,1); } } ArrayList<Integer> arrayList1=new ArrayList<>(); ArrayList<Integer> arrayList2=new ArrayList<>(); for(Map.Entry<Integer,Integer> kv:tm1.entrySet()){ if((kv.getValue()^1)==0){ arrayList1.add(kv.getKey()); } } for(Map.Entry<Integer,Integer> kv:tm2.entrySet()){ if((kv.getValue()^1)==0){ arrayList2.add(kv.getKey()); } } int temp=0; for(int i=0;i<arrayList1.size();i++){ for(int j=0;j<arrayList2.size();j++){ temp^=(arrayList1.get(i)+arrayList2.get(j)); } } System.out.print(temp); //3,輸出 } } /* 5 1 2 1 0 0 1 2 3 0 0 2//樣例1輸出結果 6 4 6 0 0 3 3 0 5 6 5 0 3 8//樣例2輸出結果 */