Java通过与Recursive的数组中的乘法合并相同的数字

时间:2016-11-17 13:53:16

标签: arrays merge multiplication

我想写一个方法,通过乘法合并数组中的相同值。我想用递归来做。 如果有相似的数字,则应合并任何数字序列。 因此,例如,如果我有数字1,2,5,5,4,它应该变为“1 2 25 4”或5,5,5,6变为“125 6”。

有人可以帮忙吗?

1 个答案:

答案 0 :(得分:0)

这种方法利用分而治之,应该在O(n log n)中运行。

package edu.gwu.seas.cs6212.hw3;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.TreeMap;

public class Tester {
    public static void main(String [] args){
        System.out.println("Merging 1, 2, 5, 5, 4: ");
        int [] originalArray = {1, 2, 5, 5, 4};
        int [] mergedArray = mergeSequences(originalArray);
        StringBuilder sb = new StringBuilder();
        for(int element : mergedArray){
            sb.append(element);
            sb.append(",");
        }
        sb.deleteCharAt(sb.length()-1); //Remove final comma
        System.out.println(sb.toString());
        sb.delete(0, sb.length());
        System.out.println("Merging 5, 5, 5, 6: ");
        int [] originalArray2 = {5, 5, 5, 6};
        int [] mergedArray2 = mergeSequences(originalArray2);
        for(int element : mergedArray2){
            sb.append(element);
            sb.append(",");
        }
        sb.deleteCharAt(sb.length()-1); //Remove final comma
        System.out.println(sb.toString());
    }

    private static int [] mergeSequences(int [] originalArray){

        Map<Integer,Integer> indiciesMap = mergeDivideAndConquer(originalArray, 0, originalArray.length -1, new TreeMap<Integer,Integer>());
        int indexCounter = 0;
        List<Integer> mergedList = new ArrayList<Integer>();
        Iterator<Entry<Integer, Integer>> it = indiciesMap.entrySet().iterator();
        if(it.hasNext()){
            while(it.hasNext()){
                Entry<Integer,Integer> firstEntry = it.next();
                int firstSequenceBeginIndex = firstEntry.getKey();
                int firstSequenceEndIndex = firstEntry.getValue();
                while(indexCounter < firstSequenceBeginIndex){
                    mergedList.add(originalArray[indexCounter]);
                    indexCounter++;
                }
                //Now we've reached first entry
                int multiplicativeSum = 1;
                while(indexCounter <= firstSequenceEndIndex){
                    multiplicativeSum *= originalArray[indexCounter];
                    indexCounter++;
                }
                mergedList.add(multiplicativeSum);
            }
            //Add remaining elements
            while(indexCounter < originalArray.length){
                mergedList.add(originalArray[indexCounter++]);
            }

        } else{
            for(int element : originalArray){
                mergedList.add(element);
            }
        }
        return mergedList.stream().mapToInt(i -> i).toArray();
    }

    private static Map<Integer,Integer> findCrossingArray(final int [] originalArray, final int i, final int midpoint, 
            final int j, Map<Integer,Integer> indiciesMap){
        int leftIndexOfSequence = -1;
        for(int leftCounter = midpoint; leftCounter >= i; leftCounter--){
            if(originalArray[leftCounter] == originalArray[midpoint]){
                leftIndexOfSequence = leftCounter;
            } else{
                break;
            }
        }
        int rightIndexOfSequence = midpoint;
        for(int rightCounter = midpoint + 1; rightCounter <= j; rightCounter++){
            if(originalArray[rightCounter] == originalArray[midpoint]){
                rightIndexOfSequence = rightCounter;
            } else{
                break;
            }
        }
        if(leftIndexOfSequence != -1 && leftIndexOfSequence != rightIndexOfSequence){
            indiciesMap.put(leftIndexOfSequence, rightIndexOfSequence);
        }
        return indiciesMap;
    }

    private static Map<Integer,Integer> mergeDivideAndConquer(final int [] originalArray, final int i, final int j, Map<Integer,Integer> indiciesMap){
        //Base case
        if(j == i){
            return indiciesMap;
        }
        //Divide recursively into smaller subproblems
        int midpoint = Math.floorDiv((i + j),2);
        Map<Integer,Integer> left = mergeDivideAndConquer(originalArray, i, midpoint, indiciesMap);
        Map<Integer,Integer> right = mergeDivideAndConquer(originalArray, midpoint + 1, j, indiciesMap);
        //Combine subsolutions
        return findCrossingArray(originalArray, i, midpoint, j, indiciesMap);

    }
}
相关问题