问题描述:
设计一个链表,插入50个随机整数。每次从链表中找出两个最小整数,将这两个整数从链表中移除,再将这两个整数之和作为新的数字加入链表,直至链表中只有一个数字
将链表换成数组,执行上述过程,比较数组和链表的差异。
问题分析:
1. 由于在整个过程中,链表需要变动,所以采用LinkedList效率会比较好。
2. 但数组就不一样了,数组是顺序存储的,一旦移除某个元素,这个元素后面的元素都要往前推,而插入一个元素的话,其后的元素都要往后以一个位置。
这样做的话,效率会非常低。
问题解决:
对于数组,采用如下小技巧提高效率:
假设最小的两个数为A和B,它们的和为C,数组的第一个位置的元素为D
把C的值赋给A,交换B和D。
这样,出了数组第一个位置的元素,其他都是我们需要的数据。
就这样循环,直到数组是剩下一个元素为止。
代码如下:
package com.test.ly; import java.util.LinkedList; import java.util.List; import java.util.Random; public class TestList { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub List<Integer> lst = new LinkedList<Integer>(); int[] arr = new int[50]; generateData(lst,50); generateData(arr,arr.length); System.out.println("sum from List is :"+ getSum(lst)); System.out.println("sum from Arr is :"+ getSum(arr)); } @SuppressWarnings("unchecked") private static Object generateData(Object obj,int size) { if(obj == null) return null; Random rdm = new Random(); if(obj instanceof LinkedList){ for(int i = 0;i<size;i++){ ((LinkedList<Integer>) obj).add(rdm.nextInt()); } }else if(obj instanceof int[]){ for(int i=0;i<size;i++){ ((int[]) obj)[i] = rdm.nextInt(); } } return obj; } @SuppressWarnings({ "unchecked" }) private static int getSum(Object obj) { List<Integer> smallest = null; if(obj instanceof LinkedList){ LinkedList<Integer> sumList = (LinkedList<Integer>) obj; if(sumList.isEmpty()){ return 0; } while(sumList.size() != 1){ smallest = find(sumList,0); sumList.removeAll(smallest); sumList.add(smallest.get(0)+smallest.get(1)); } return sumList.get(0); } /** * need to improve */ if(obj instanceof int[]){ int[] sumArr = (int[]) obj; if(sumArr == null || sumArr.length ==0){ return 0; } int startIndex = 0; while( (sumArr.length-startIndex) != 1){ smallest = find(sumArr,startIndex); /** * replace * * replace the smallest one with sumArr[startIndex] * replace the second smallest one with sumArr[startIndex+1] * and the startIndex++ * * with the above method, you can ellipsis the trimming array loops, * and it also improve the efficiency */ int tempSum = sumArr[smallest.get(0)] + sumArr[smallest.get(1)]; sumArr[smallest.get(0)] = sumArr[startIndex]; sumArr[smallest.get(1)] = sumArr[startIndex+1]; sumArr[startIndex+1] = tempSum; startIndex ++; // for(int i = smallest.get(0);i<sumArr.length-1;i++){ // sumArr[i]=sumArr[i+1]; // } // for(int i = smallest.get(1);i<sumArr.length-1;i++){ // sumArr[i]=sumArr[i+1]; // } } return sumArr[sumArr.length-1]; } return 0; } @SuppressWarnings("unchecked") private static List<Integer> find(Object obj,int startIndex) { List<Integer> resultList = new LinkedList<Integer>(); int smallest = 0; int secondSmallest = 0; if(obj == null){ resultList.add(smallest); resultList.add(secondSmallest); return resultList; } if(obj instanceof LinkedList){ LinkedList<Integer> lst = (LinkedList<Integer>) obj; smallest= lst.get(0); secondSmallest = lst.get(1); if(lst.size()>2) for(int index =2;index< lst.size();index++){ int current = lst.get(index); if(current < smallest){ smallest = current; }else if( current <secondSmallest){ secondSmallest = current; } } } /** * in this section, we use the index */ if(obj instanceof int[]){ int[] arr = (int[]) obj; smallest= startIndex; secondSmallest = startIndex+1; if( (arr.length-startIndex) > 2) for(int index =startIndex+2;index< arr.length;index++){ int current = arr[index]; if(current < arr[smallest]){ smallest = index; }else if( current <arr[secondSmallest]){ secondSmallest = index; } } } resultList.add(smallest); resultList.add(secondSmallest); return resultList; } }