繁体   English   中英

如何仅使用递归合并2个排序的链表

[英]how can I merge 2 sorted linked lists by only using recursion

我正在编写一个程序来计算小于1,000,000的3和5的倍数。 我有一个函数可以正确返回2的独立链表中3和5的倍数。 现在,我想将这2个链接列表合并为一个排序的非重复链接列表。 我尝试了以下代码,但由于我正在使用链接列表库,因此“ next”在我的情况下不是已定义的元素。 除了线性运算-O(n log n)之外,我再也不能将运行时炸毁了。

private static LinkedList<Integer> mergeLists(LinkedList<Integer> ll1, LinkedList<Integer> ll2) {

    LinkedList<Integer> finalList = new LinkedList();

    if (ll1 == null)
        return ll2;
    if (ll2 == null)
        return ll1;

    if (ll1.get(0) < ll2.get(0)) {
        ll1.next = MergeLists(ll1.next, ll2);
        return ll1;
    }
    else {
        ll2.next = MergeLists(ll2.next, ll1);
        return ll2;
    }
}

对于所有可能关心的人,这就是我最终要做的事情:

import java.util.*;

public class Multiples {

    private static LinkedList<Integer> calculate_multiples(int factor, int limit) {

        LinkedList<Integer> muls = new LinkedList<Integer>();
        boolean result_not_maxed = true;

        int counter = 1;
        while (result_not_maxed) {

            int local_result = factor*counter;
            if (local_result < limit) {

                muls.add(local_result);
                counter++;
            }
            else
                result_not_maxed = false;
        }

        return muls;
    }

    private static LinkedList<Integer> mergeLists(LinkedList<Integer> ll1, LinkedList<Integer> ll2) {

        LinkedList<Integer> finalList;
        Set<Integer> finalSet = new HashSet<>();

        finalSet.addAll(ll1);
        finalSet.addAll(ll2);

        finalList = new LinkedList<Integer>(finalSet);

        return finalList;
    }

    private static int sum(LinkedList<Integer> ll) {

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

            sum += ll.get(i);
        }

        return sum;
    }

    public static void main(String [] args) {

        LinkedList<Integer> ll_3s = Multiples.calculate_multiples(3, 1000000);
        LinkedList<Integer> ll_5s = Multiples.calculate_multiples(5, 1000000);

        LinkedList<Integer> finalList = new LinkedList<Integer>();
        finalList = Multiples.mergeLists(ll_3s, ll_5s);

        int result = sum(finalList);
        System.out.print("Sum is: " + result);
    }
}

当OP请求时,将两个排序的LinkedList合并的递归算法,并跳过重复项。 这在O(n)中运行,其中n是两个列表中元素的总数。

请注意,此(递归)对于您陈述的用例1和3的整数倍小于1百万根本不实际。

public static void main(String[] args) {
  LinkedList<Integer> list1 = Lists.newLinkedList(
      Arrays.asList(3, 6, 9, 12, 15, 18, 21, 24, 27, 30));
  LinkedList<Integer> list2 = Lists.newLinkedList(
      Arrays.asList(5, 10, 15, 20, 25, 30));

  LinkedList<Integer> combined = combine(list1, list2);
  System.out.println(combined);
}

private static LinkedList<Integer> combine(LinkedList<Integer> list1,
    LinkedList<Integer> list2) {
  LinkedList<Integer> combined = new LinkedList<>();
  combine(list1, list2, combined);
  return combined;
}

private static void combine(LinkedList<Integer> list1,
    LinkedList<Integer> list2, LinkedList<Integer> combined) {
  if (list1.size() > 0 && list2.size() > 0) {
    if (list1.peek() == list2.peek()) {
      list1.remove();
    } else if (list1.peek() < list2.peek()) {
      combined.add(list1.remove());
    } else {
      combined.add(list2.remove());
    }
  } else if (list1.size() > 0 && list2.size() == 0) {
      combined.add(list1.remove());
  } else if (list1.size() == 0 && list2.size() > 0) {
    combined.add(list2.remove());
  } else {
    return;
  }
  combine(list1, list2, combined);
}

如果您可以访问Java 8,则可以使用流更有效地完成此操作:

Set<Integer> mySet= IntStream.range(0, 1000000)
    .filter(n -> n % 3 == 0 || n % 5 == 0)
    .collect(Collectors.toSet());

这比创建单独的列表然后合并要快得多。

如果确实要合并两个列表:

Set<Integer> mySet = Streams.concat(list1.stream(), list2.stream())
    .collect(Collectors.toSet());

如果您没有Java 8,则只需将两个列表都添加到Set TreeSetSortedSet因此您无需担心排序:

Set<Integer> final = new TreeSet<>();
if (list1 != null)
    final.addAll(list1);
if (list2 != null)
    final.addAll(list2);
return final;

Java 7非流版本:

private static LinkedList<Integer> mergeLists(LinkedList<Integer> ll1, LinkedList<Integer> ll2) {
    TreeSet<Integer> set = new TreeSet<>();
    set.addAll(ll1);
    set.addAll(ll2);
    return new LinkedList<Integer>(set);
}

您不需要为此合并两个列表。 将3和5插入数组中。 维护三个辅助变量1.divisible_by_five 2. divisible_by_three和3.max最初,divisible_by_five = 5,divisible_by_three = 3,max = 5

do{
    if(divisible_by_three+3 < divisible_by_five+5){
        divisible_by_three += 3;
        max = divisible_by_three;
    }
    else if(divisible_by_three+3 > divisible_by_five+5){
        divisible_by_five += 5;
        max = divisible_by_five;
    }
    else{
        divisible_by_3 +=3;
        max = divisible_by_five = divisible_by_3;
    }
    insertIntoList(max);
}while(max<100000);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM