(第22讲)java数组的一些编程题

1.      要求输入一组英文字符串数组,让这个字符串数组中前面一个元素的最后一个字母和下一个元素的首位上的字母相等,并且每个元素的长度大于等于2且小于等于100

publicstatic void main(String[] a )   {

                    Two t = new Two();

                    System.out.println(t.s());       }

          public int s(){          

         //      String[]args={"abcd","def","fgr","rtg"};

                    String[] args={"abcd","def","A","rtg"};

       for (int i=0;i<args.length-1;i++){

                boolean b1=args[i].matches("[a-z]+");

                boolean b2 = args[i].length()>=2 ;

                boolean b3 = args[i].length()<=100 ;   

                if(b1&&b2&&b3){

                        char  c1= args[i].charAt(args[i].length()-1);

                        char  c2 = args[i+1].charAt(0);

                          if(c1==c2){                          b= Two.show1();                                    

                          }else{    b=  Two.show2();

                                      break;                 }

                }else{

                          b= Two.show2();

                          break;               }      }

       if(b==true){

                return 1;

      

       }else{

                return -1;       }   

          }

         public static boolean show1(){

                   return true;

         }

         public static boolean show2(){

                   return false;

         } 

2、快速找出一个数组中的最大数、第二大数。

     思路:如果当前元素大于最大数 max,则让第二大数等于原来的最大数 max,再把当前元素的值赋给 max。如果当前的元素大于等于第二大数secondMax的值而小于最大数max的值,则要把当前元素的值赋给 secondMax。

public static void main(String[] a1 )   {

                    Two t = new Two();

                    int[] a={12,233,4232,2,23,1,234};

                    t.compare(a);

         }

          public void compare(int[] a){

                    int max = a[0];

                    int max2 = a[a.length-1];

                    for(int i=0;i<a.length;i++){

                             if(a[i]>max){

                                      max2 = max;

                                      max = a[i];

                             }else if(a[i]>max2 && a[i]<max){

                                      max2 = a[i];                      }               }

                    System.out.println("这个数组最大的是:"+max);

                    System.out.println("这个数组第二大的是:"+max2);       }

法二:

public static void main(String[] a1 )   {

                    Two t = new Two();

                    int[] a={12,233,4232,2,23,1,234};

                    java.util.Arrays.sort(a);

System.out.println(java.util.Arrays.toString(a));//输出数组可以不用遍历

                    System.out.println("这个数组最大的是:"+a[a.length-1]);

                    System.out.println("这个数组第二大的是:"+a[a.length-2]);

         }

3、试着用最小的比较次数去寻找数组中的最大值和最小值。

解法一:扫描一次数组找出最大值;再扫描一次数组找出最小值。比较次数2N-2

解法二:将数组中相邻的两个数分在一组,每次比较两个相邻的数,将较大值交换至这两个数的左边,较小值放于右边。对大者组扫描一次找出最大值,对小者组扫描一次找出最小值。

比较1.5N-2次,但需要改变数组结构

解法三:

每次比较相邻两个数,较大者与MAX比较,较小者与MIN比较,找出最大值和最小值。

方法如下:先将一对元素互相进行比较,然后把最小值跟当前最小值进行比较,把最大值跟当前最大值进行比较。因此每两个元素需要3次比较。如果n为奇数,那么比较的次数是3*(n/2)次比较。如果n为偶数,那么比较的次数是3n/2-2次比较。因此,不管是n是奇数还是偶数,比较的次数至多是1.5n :

public static void main(String[] a1 )   {

                    Two t = new Two();

                    int[] a={12,233,4232,-12,23,1,234};

                    t.compare(a);         }

           public void compare(int[] a){

                    int max = a[0];

                    int min = a[a.length-1];

                    for(int i=0;i<a.length-1;i++){

                             if(a[i]>a[i+1]){

                                      if(a[i]>max){

                                                max = a[i];

                                      }

                                      if(a[i+1]<min){

                                                min = a[i+1];                              }                        }               }

                    System.out.println("这个数组的最大值是:"+max);

                    System.out.println("这个数组的最小值是:"+min);

          }

4、重排问题

给定含有n个元素的整型数组a,其中包括0元素和非0元素,对数组进行排序,要求:

1、排序后所有0元素在前,所有非零元素在后,且非零元素排序前后相对位置不变

2、不能使用额外存储空间

例子如下

输入 0、3、0、2、1、0、0

输出 0、0、0、0、3、2、1

分析: 如果当前位置上为0,他前面的不为0 ,则交换

public static void main(String[] a1 )   {

                   int[]a ={0,1,2,0,3,0,2,0,0};

                   for(intj=0;j<a.length;j++) {

                            for(inti=1;i<a.length;i++){                                   

                                     if(a[i]== 0&& a[i-1]!=0){

                                               a[i]=a[i-1];

                                               a[i-1]=0;

                                     }

                            }

                   }                

                   System.out.println(java.util.Arrays.toString(a));

          }

5、找出绝对值最小的元素

给定一个有序整数序列(非递减序),可能包含负数,找出其中绝对值最小的元素,比如给定序列 -5、-3、-1、2、8 则返回1。

分析:由于给定序列是有序的,而这又是搜索问题,所以首先想到二分搜索法,只不过这个二分法比普通的二分法稍微麻烦点,可以分为下面几种情况

    如果给定的序列中所有的数都是正数,那么数组的第一个元素即是结果。

    如果给定的序列中所有的数都是负数,那么数组的最后一个元素即是结果。

    如果给定的序列中既有正数又有负数,那么绝对值的最小值一定出现在正数和负数的分界处。

为什么?因为对于负数序列来说,右侧的数字比左侧的数字绝对值小,如上面的-5、-3、-1,而对于整整数来说,左边的数字绝对值小,比如上面的2、8,将这个思想用于二分搜索,可先判断中间元素和两侧元素的符号,然后根据符号决定搜索区间,逐步缩小搜索区间,直到只剩下两个元素。

单独设置一个函数用来判断两个整数的符号是否相同

public static void main(String[] a1 )   {

                   int[]a ={-5,-3,12,-1,90,2,9};

                   int[]b = new int[a.length];

                    for(int i=0;i<a.length;i++){

                            b[i]= Math.abs(a[i]);                                 }

                    int minAbs = b[0];

                    for(int i=0;i<b.length;i++){

                             if(b[i]<minAbs){

                                      minAbs = b[i];                            }               }

                   System.out.println(java.util.Arrays.toString(a));

                   System.out.println(java.util.Arrays.toString(b));

                   System.out.println(minAbs);   }

6、从长度为n的数组(元素互不相同)中任意选择m个数的所有组合。

7、从长度为n的数组(元素有可能相同)中任意选择m个数的所有组合。

先对数组进行排序,然后设置一个标记pre,记录前一个选择的数字,然后进行比较。

import java.util.*;

public class  Two {

          public static void main(String[] a1 )   {

               String[] data = {"1","2", "2","3", "4", "5"};

                 int num = 3;

                 List<List<String>> result =parade(Arrays.asList(data), num);

                  for (List<String> x : result) {

                     System.out.println(x);

                 } 

                /* //相当于

                 for (int i=0;i<result.size();i++) {

                     System.out.println(result.get(i));

                 }*/

                System.out.printf("total:%s\n", result.size());

             }       

             public static List<List<String>>parade(List<String> data, int num) {

                 List<List<String>> result =new ArrayList<List<String>>();

                 if (num == 1) { //只排一个元素的时候(递归结束条件)

                     for (String s : data) {

                         List<String> l = newArrayList<String>();

                         l.add(s);

                         result.add(l); //每个元素分别保存到结果集

                     }

                     return result; //并返回结果集

                 }

                 for (int i=0; i<data.size(); i++) {//num>1,即排多个元素的时候,循环

                     List<String> list = newArrayList<String>(data);

               list.remove(i);//去掉当前循环的元素作为下次递归的参数,即剩余的元素做递归

                     List<List<String>> sub= parade(list, num-1); //递归调用

                     for (List<String> l : sub) {//然后循环递归得到的结果

                         l.add(0, data.get(i)); //把当前元素排在每个结果的前面

                         result.add(l); //并保存到结果集

                     }

                 }

                 return result; //最后返回结果集

             }

         }

8、三色旗排序问题

假设有一根绳子,上面有一些红、白、蓝色的旗子。起初旗子的顺序是任意的,现在要求用最少的次数移动这些旗子,使得它们按照蓝、白、红的顺序排列。注意只能在绳子上操作,并且一次只能调换两个旗子。

public class Two {

         publicstatic final char BLUE = 'b';

         publicstatic final char RED = 'r';

         publicstatic final char WHITE = 'w';

         publicstatic final char[] color = { 'r', 'w', 'b', 'w', 'w', 'b', 'r', 'b', 'w', 'r'};

         //交换彩旗的方法

         publicstatic void SWAP(int x, int y) {

                   chartemp = color[x];

                   color[x]= color[y];

                   color[y]= temp;

         }

         publicstatic void main(String[] a1) {

                   intbFlag = 0;

                   intwFlag = 0;

                   intrFlag = color.length - 1;

                   for(int i = 0; i < color.length; i++) {

                            System.out.print(color[i]);

                   }

                   System.out.println();

                   while(wFlag <= rFlag) {

                            if(color[wFlag] == WHITE) {

                                     wFlag++;

                            }else if (color[wFlag] == BLUE) {

                                     SWAP(bFlag,wFlag);

                                     bFlag++;

                                     wFlag++;

                            }else {

                                     while(wFlag < rFlag && color[rFlag] == RED) {

                                               rFlag--;

                                     }

                                     SWAP(rFlag,wFlag);

                                     rFlag--;                        }

                   }

                   for(int i = 0; i < color.length; i++) {

                            System.out.print(color[i]);

                   }

                   System.out.println();        }}

9、一个int数组,里面数据无任何限制,要求求出所有这样的数a[i],其左边的数都小于等于它,右边的数都大于等于它。能否只用一个额外数组和少量其它空间实现。

分析:最原始的方法是检查每一个数 array[i] ,看是否左边的数都小于等于它,右边的数都大于等于它。这样做的话,要找出所有这样的数,时间复杂度为O(N^2)。

其实可以有更简单的方法,我们使用额外数组,比如rightMin[],来帮我们记录原始数组array[i]右边(包括自己)的最小值。假如原始数组为: array[] = {7, 10, 2, 6, 19, 22, 32}, 那么rightMin[] = {2, 2,2, 6, 19, 22, 32}. 也就是说,7右边的最小值为2, 2右边的最小值也是2。

有了这样一个额外数组,当我们从头开始遍历原始数组时,我们保存一个当前最大值 max,如果当前最大值刚好等于rightMin[i],那么这个最大值一定满足条件,还是刚才的例子。

第一个值是7,最大值也是7,因为7 不等于 2,继续,

第二个值是10,最大值变成了10,但是10也不等于2,继续,

第三个值是2,最大值是10,但是10也不等于2,继续,

第四个值是6,最大值是10,但是10不等于6,继续,

第五个值是19,最大值变成了19,而且19也等于当前rightMin[4] = 19, 所以,满足条件。如此继续下去,后面的几个都满足。

public class Two {

         publicstatic void main(String s[]) {

                   try{

                            smallLarge(newint[] { 7, 10, 2, 6, 19, 22, 32 });

                   }catch (Exception e) {

                            e.printStackTrace();

                   }

         }

         publicstatic void smallLarge(int[] array) throws Exception {

                   if(array == null || array.length < 1) {

                            thrownew Exception("the array is null or the array has no element!");

                   }

                   int[]rightMin = new int[array.length];

                   rightMin[array.length- 1] = array[array.length - 1];

                   for(int i = array.length - 2; i >= 0; i--) {

                            if(array[i] < rightMin[i + 1]) {

                                     rightMin[i]= array[i];

                            }else {

                                     rightMin[i]= rightMin[i + 1];

                            }

                   }

                   intleftMax = Integer.MIN_VALUE;

                   for(int i = 0; i < array.length; i++) {

                            if(leftMax <= array[i]) {

                                     leftMax= array[i];

                                     if(leftMax == rightMin[i]) {

                                               System.out.println(leftMax);

                                     }

                            }

                   }

         }

}

 10、整数的拆分问题

如,对于正整数n=6,可以拆分为:

6

5+1

4+2

4+1+1

3+3

3+2+1

3+1+1+1

2+2+2

2+2+1+1

2+1+1+1+1

1+1+1+1+1+1

现在的问题是,对于给定的正整数n,程序输出该整数的拆分种类数

public class Two {

           /**正整数加法不同的分解法

    * @param sum:和  * @param max:最大值  * @param data:记录不同的加法形式      * @param index:加法分解数的最大个数      * @return 分解个数      */ 

   public static int splitInteger(int sum, int max, int[] data, int index) { 

       if (max > sum) max = sum; 

       if (sum < 1 || max < 1) return 0; 

       if (sum == 1 || max == 1) { 

           if (sum == 1) { 

                data[index] = sum; 

                print(data, index+1); 

           } else { 

                for (int i = 0; i < sum;i++) { 

                   data[index++] =max;                  } 

                print(data, index);              } 

           return 1;          } 

       if (sum == max) { 

           data[index] = max; 

           print(data, index+1); 

           return 1 + splitInteger(sum, max-1, data, index); 

       } else if (sum > max) { 

           data[index] = max; 

           //一定注意这里的先后顺序 

   return splitInteger(sum-max, max, data, index+1) + splitInteger(sum,max-1, data, index);            

       } else {  

           //sum < max 

           return splitInteger(sum, sum, data, index);          }    }       

        public static void print(int[] data, intindex) {  //打印数组 

       for (int i = 0; i < index -1; i++) { 

           System.out.print(data[i] + "+");          } 

       System.out.println(data[index-1]);     } 

* 正整数加法不同分解的个数:最大值为max,和为sum的加法个数

递归形式: f(sum, max) = f(sum-max, max) + f(sum, max-1); 

   public static int count(int sum, int max) { 

       if (sum < 1 || max < 1) return 0; 

       else if (sum == 1 || max == 1){  

           return 1; 

       } else if (sum < max) { 

           return count(sum,sum); 

       } else if (sum == max) { 

           return 1+count(sum, sum-1); 

       } else {  

           return count(sum, max-1)+count(sum-max,max);         }     }       

   public static void main(String[] args) { 

       int n = 4; 

       int[] data = new int[n]; 

       System.out.println("正整数\'" + n + "\'可以分解为如下不同的加法形式:"); 

        System.out.println("正整数\'" +n + " \'加法分解个数为:\t" + splitInteger(n,n,data,0)); 

       n = 100; 

       System.out.println("正整数\'" + n + "\'加法分解个数为(包含本身):\t" +count(n,n)); 

   System.out.println("正整数\'" + n + "\'加法分解个数为(不包含本身):\t" +count(n,n-1)); 

   }  } 

 11、在数组中寻找和为给定值的组合

 publicclass Two {

         staticint[] arr ={1, 5, 9, 3, 4, 7, 6, 2, 8};

   static int maxIndex = arr.length - 1;// 索引最大值

   static int sum = 11;// 求两个数的和等于的值

   public static void main(String[] args)

   {        find1(arr);    }

// 1.所有数字两两组合,计算;时间复杂度O(n*n)

// 2.先把数组排序,然后利用二分查找在数组中查找,判断sum-arr[i]是否在数组中;时间复杂度O(n*longn)

// 3.先对数组排序i=0,j=n-1,如果:sum<arr[i]+arr[j]i++;如果:sum<arr[i]+arr[j] j--

// 如果有序,直接两个指针两端扫描,时间O(N);如果无序,先排序后两端扫描,时间O(N*logN+N)=O(N*logN),空间始终都为O(1)

 

 static void find1(int[] arr) {

       Arrays.sort(arr);// 对数组排序

       for (int i = 0, j = maxIndex; i < j;)

       {

           if (arr[i] + arr[j] == sum)

           {

                System.out.println(sum + "= " + arr[i] + " + " + arr[j]);

                i++;// 没有这一句死循环

           }

           else if (arr[i] + arr[j] < sum)

           {

                i++;

           }

           else

           {

                j--;

           }        }    }}

 12、求数组中两个元素差的最大值

import java.util.*;

public class Two {

         publicstatic void main(String[] a1) {

                   List<Integer>result = new ArrayList<Integer>();

                    int[] aa = {12,2,34,54,65,3,2,5,-12,4,0};

                    for(int i =0;i<aa.length;i++){

                             for(int j =0; j<aa.length && j!=i;j++){

                                      int cha = aa[i]-aa[j];

                                      int cha2 = aa[j]-aa[i];

                                      result.add(cha);

                                      result.add(cha2);

                             }

                    }

                    int min = result.get(0);

                    for(int i =0;i<result.size();i++){

                             if(result.get(i)< min){

                                      min = result.get(i);

                             }

                    }

                    System.out.println("两个元素的差为:");

                    for(Integer x : result){

                             System.out.print(x+"  ");

                    }

                    System.out.println();

                    System.out.println("两个元素的差总共有"+result.size()+"个");

                    System.out.println("两个元素的差的最小值时:"+min);

         }

}

13、输入一个正数 n,输出所有和为 n 连续正数序列。

例如输入 15,由于 1+2+3+4+5=4+5+6=7+8=15,所以输出 3 个连续序列 1-5、4-6 和 7-8。

package com.tankxiancheng;

public class Two {

           public static void getAns(int n){

              int beg=1;

              int sum=1;

              int cur=1;            

             while(beg<=n/2+1){      

               if(sum==n){

                 for(int k=beg;k<=cur;k++){

                          if(k == cur){

                                    System.out.print(k+"=15");

                          }else{

                          System.out.print(k+"+");

                          }

                 }

                 System.out.println();

                 sum=sum-beg;

                 beg++;

                 cur++;

                 sum+=cur;               

               }

                if(sum>n){         

                  sum=sum-beg;

                  beg++;          

               }else     {

                cur++;

                sum+=cur;

                }     

             } 

           }

           public static void main(String[] args) {

             getAns(15);

           }

         }

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值