有p個小孩,c個糖果,剛開始第1個小孩發一個糖果,第2個小孩發兩個糖果,第p個小孩發p個糖果,若是糖果沒有發完,就接着【注意】第1個小孩發p+1個糖果.....第p個小孩發2*p個糖果,若是糖果尚未發完,就繼續下一輪,第1個小孩發2*p+1個糖果,...java
方法一,遍歷【這種方法太low了就摺疊一下】算法
package com.cnblogs.mufasa.Main1; import java.util.Scanner; public class Main { public static int[] getCandies(int c,int p){ int[] pGet=new int[p]; int preNum=1; while (c!=0){ for(int i=0;i<p;i++){ if(preNum<c){ pGet[i]+=preNum; c-=preNum; preNum++; }else { pGet[i]+=c; return pGet; } } } return null; } public static void main(String[] args) { Scanner sc=new Scanner(System.in); int c=Integer.valueOf(sc.next()); int p=Integer.valueOf(sc.next()); int[] pGet=getCandies(c,p); System.out.print("["); for(int i=0;i<p-1;i++){ System.out.print(pGet[i]+","); } System.out.println(pGet[p-1]+"]"); } } /* 7 4 */
方法二,數學推導【算法複雜度急速下降】除了,推理的時候複雜一些,其餘都還好數組
package com.cnblogs.mufasa.Main1; import java.util.Scanner; public class Main1 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); // int c = Integer.valueOf(sc.next()); // int p = Integer.valueOf(sc.next()); //0,測試 int c=45,p=4; int lineSum=(1+p)*p/2;//1+2+3+...+p的總數 int leve=0,preCan=c; //1,1先判斷出是在第幾層中斷【正確】 while (true){ if(preCan<leve*p*p+lineSum){ break; } preCan-=(leve*p*p+lineSum); leve++; } int[] pGet=new int[p]; //1,2直接算出各個小朋友持有的糖果數【仍是要區分第0層與其餘層的區別】 if(leve!=0){//1,2,2 非第0層中斷 int temp=p*(leve-1)*leve/2; for(int i=1;i<=p;i++){ pGet[i-1]=temp+i*leve; } } int preSta=p*leve; for(int i=1;i<=p;i++){ if(preCan<preSta+i){ pGet[i-1]+=preCan; break; }else { pGet[i-1]+=(preSta+i); } preCan-=(preSta+i); } //3數據輸出 System.out.print("["); for(int i=0;i<p-1;i++){ System.out.print(pGet[i]+","); } System.out.println(pGet[p-1]+"]"); } }
方法一:使用HashSet和TreeSet解決問題,可是隻AC60%!!!多是耗時太多【時間複雜度大】理解簡單易懂ide
package com.cnblogs.mufasa.Main2; import java.util.ArrayList; import java.util.HashSet; import java.util.Scanner; import java.util.TreeSet; public class Main { public static void main(String[] args) { Scanner sc=new Scanner(System.in); String str0=sc.next(); String str1=sc.next(); String[] strs0=str0.substring(1,str0.length()-1).split(","); String[] strs1=str1.substring(1,str1.length()-1).split(","); if(str0.length()<str1.length()){ String[] temp=strs0; strs0=strs1; strs1=temp; } HashSet<Integer> hs=new HashSet<>(); TreeSet<Integer> tsOut=new TreeSet<>(); for(int i=0;i<strs0.length;i++){ hs.add(Integer.valueOf(strs0[i])); } for(int i=0;i<strs1.length;i++){ int temp=Integer.valueOf(strs1[i]); if(hs.contains(temp)){ tsOut.add(temp); } } System.out.print("["); for(int i=0;i<tsOut.size()-1;i++){ System.out.print(tsOut.pollFirst()+","); } System.out.print(tsOut.pollFirst()); System.out.println("]"); } } /* [1,2,2,1,3] [2,2,3] [2,3] */
方法二:直接使用遍歷進行,省略了計算hash值以及進行查找的費時操做【算法複雜度下降而且擁有兩個光標進行判斷】測試
package com.cnblogs.mufasa.Main2_1; import java.util.*; public class Main { public static void main(String[] args) { Scanner sc=new Scanner(System.in); // String str0=sc.next(); // String str1=sc.next(); //測試 String str0="[1,2,2,1,3]"; String str1="[2,2,3]"; String[] strs0=str0.substring(1,str0.length()-1).split(","); String[] strs1=str1.substring(1,str1.length()-1).split(","); if(str0.length()<str1.length()){ String[] temp=strs0; strs0=strs1; strs1=temp; } int[] arr0=new int[strs0.length]; int[] arr1=new int[strs1.length]; for(int i=0;i<arr0.length;i++){ arr0[i]=Integer.valueOf(strs0[i]); } for(int i=0;i<arr1.length;i++){ arr1[i]=Integer.valueOf(strs1[i]); } Arrays.sort(arr0);//排序 Arrays.sort(arr1); ArrayList<Integer> tsOut=new ArrayList<>(); int index0=0,index1=0; while (index0<arr0.length&&index1<arr1.length){ if(arr0[index0]==arr1[index1]){ if(!tsOut.contains(arr0[index0])){ tsOut.add(arr0[index0]); } index0++; }else if(arr0[index0]<arr1[index1]){ index0++; }else { index1++; } } System.out.print("["); for(int i=0;i<tsOut.size()-1;i++){ System.out.print(tsOut.get(i)+","); } System.out.print(tsOut.get(tsOut.size()-1)); System.out.println("]"); } } /* [1,2,2,1,3] [2,2,3] [2,3] */
例如:有1,2,5面值的硬幣,請問11元錢最少多少硬幣能夠湊成,若是沒法湊成直接輸出-1【以前AC80%緣由找到了,是輸出-1這個沒有安排上】spa
package com.cnblogs.mufasa.Main3; import java.util.ArrayList; import java.util.Comparator; import java.util.Scanner; import java.util.Stack; //遞歸調用,好像能夠很好的解決問題 public class Main { private final static int NUM=Integer.MAX_VALUE; private static Stack<Integer> stack=new Stack<>(); static { stack.push(NUM); } public static int sinFin(int[] sinM,int m,int num,int index){ if(num>stack.peek()){ return NUM; } if(m==0){//1,1錢已經湊夠 stack.push(num); return num; }else if(index==0&&m%sinM[0]!=0){//1,2達到終點,可是不能湊成整數倍,返回一個最大值 return -1; }else if(index==0&&m%sinM[0]==0){//1,3到達終點,而且湊整數 stack.push(num+m/sinM[0]); return num+m/sinM[0]; } int bei=m/sinM[index]; ArrayList<Integer> arr=new ArrayList<>(); for(int i=0;i<=bei;i++){ arr.add(sinFin(sinM,m-sinM[index]*i,num+i,index-1)); } arr.sort((a,b)->{ return a-b; }); for(int temp:arr){ if(temp>0){ return temp; } } return -1; } public static void main(String[] args) { Scanner sc=new Scanner(System.in); String str0=sc.nextLine().replace(" ",""); String str1=sc.next(); String[] strs=str0.substring(1,str0.length()-1).split(","); int[] sinM=new int[strs.length]; for(int i=0;i<strs.length;i++){ sinM[i]=Integer.valueOf(strs[i]); } int m=Integer.valueOf(str1); System.out.println(sinFin(sinM,m,0,sinM.length-1)); } } /* [1, 2, 5] 11 3 [2, 4, 6] 11 */