【问题标题】:Iterating through a List with Elements which contains two Values and sum up only the connected ones (Java)遍历包含两个值的元素列表并仅总结连接的值(Java)
【发布时间】:2019-02-22 12:01:08
【问题描述】:

我需要帮助解决以下问题。 当我有一个包含两个值的元素列表时,它表示桥的起点和终点。 这些值代表“桥梁”。因此,例如 [0,1] 表示连接 island0 和 island1 的桥。

我如何遍历从 0 开始的列表,只总结连接的值而忽略其他值?

示例 1 - 每个岛屿都是间接连接的

[0,1]
[1,2]
[2,3]
[3,4]

解应该是:0+1+2+3+4 = 10

示例 2

[0,1]
[1,2]
[3,4] !!! NOT CONNECTED

解应该是:0+1+2 = 3

谢谢!!!

【问题讨论】:

  • 到目前为止你尝试了什么?
  • 我相信这叫做transitive closure。有几种算法可以做到这一点。
  • 您的问题与循环和列表有关,您必须在单向图中找到所有连接的节点,然后执行求和,否则它也可以被视为通量问题,假设在一条边中,我们为所连接节点的值的总和分配一个权重(例如,[2,3] 我们分配一个权重为 2+3),您想在其中找到所有(?)路径及其成本。 @Maurice Perry,说得好。
  • 看下面 Wolf 的解决方案:这些元素是像问题中那样有序还是无序。即 [2,3] [0,1][3,4][1,2] 给出 10 还是 5?和 [2,3] [0,1][1,2] [3,4] 的预期结果是什么? 5?还是 10 个?

标签: java list loops


【解决方案1】:

试试这个简单的解决方案

import java.util.ArrayList;
import java.util.List;

public class TestBridge {

    public static final class Bridge {
        int start;

        int end;

        Bridge(int start, int end) {
            this.start = start;
            this.end = end;
        }
    }

    private static int getSum(List<Bridge> bridges) {
        int sum = 0;
        int prevEnd = -1;
        for (Bridge bridge : bridges) {
            int actualStart = bridge.start;
            int actualEnd = bridge.end;
            if (actualStart == 0 || prevEnd == actualStart) {
                prevEnd = actualEnd;
                sum += actualEnd;
            }
        }
        return sum;
    }

    private static List<Bridge> getFirstExample() {
        List<Bridge> bridges = new ArrayList<>();
        bridges.add(new Bridge(0, 1));
        bridges.add(new Bridge(1, 2));
        bridges.add(new Bridge(2, 3));
        bridges.add(new Bridge(3, 4));
        return bridges;
    }

    private static List<Bridge> getSecondExample() {
        List<Bridge> bridges = new ArrayList<>();
        bridges.add(new Bridge(0, 1));
        bridges.add(new Bridge(1, 2));
        bridges.add(new Bridge(3, 4));
        return bridges;
    }

    public static void main(String[] args) {
        System.out.println(getSum(getFirstExample()));
        System.out.println(getSum(getSecondExample()));
    }
}

【讨论】:

  • 请注意:“实际”与“当前”的含义不同,尽管在来自德语单词“aktuell”时可能会这么认为。这就是为什么变量名actualStartactualEnd 在使用上有点混乱。
【解决方案2】:

哈根??

有一些限制可能很容易,没有限制可能会变得更复杂。有了约束,我的意思是第一座桥应该是真相的来源。想想那些案例:

[0,1]
[1,2]
[3,4]
[4,5]

(内部连接相同长度的两个部分)

[0,1]
[1,2]
[3,4]
[4,5]

(第一个桥是被排除的桥)

如果桥 1+2 已连接,3+4 已连接但未将两个部分连接在一起,会发生什么情况?我的意思是……

[0,1]
[2,3]
[3,4]
[4,5]

假设第一个桥是thruth的来源,你可以试试这个:

public class IslandConnector {
    private final List<Bridge> includedBridges = new ArrayList<>();
    private List<Bridge> excludedBridges;

    public IslandConnector(List<Bridge> bridges) {
        this.excludedBridges = new ArrayList<>();
        for(Bridge bridge : bridges) {
            if(includedBridges.isEmpty()) {
                includedBridges.add(bridge);
            }
            else {
                if(!tryIncludeBridge(bridge)) {
                    excludedBridges.add(bridge);
                }
            }           
        }
    }

    private boolean tryIncludeBridge(Bridge bridge) {
        for(Bridge includedBridge: includedBridges) {
            if(bridge.hasSameS(includedBridge)) {
                includeBridge(bridge);
                return true;
            }
        }

        return false;
    }

    private void includeBridge(Bridge bridge) {
        includedBridges.add(bridge);

        for(Bridge excludedBridge: excludedBridges) {
            if(bridge.hasSameS(excludedBridge)) {
                excludedBridges.remove(excludedBridge);
                includeBridge(excludedBridge);
            }
        }
    }

    public List<Bridge> getIncludedBridges() {
        return includedBridges;
    }

    public static void main(String... args) {
        System.out.println(new IslandConnector(Arrays.asList(
            new Bridge(0, 1),
            new Bridge(1, 2),
            new Bridge(2, 3),
            new Bridge(3, 4)
        )).getIncludedBridges());

        System.out.println(new IslandConnector(Arrays.asList(
            new Bridge(0, 1),
            new Bridge(1, 2),
            new Bridge(3, 4)
        )).getIncludedBridges());

        System.out.println(new IslandConnector(Arrays.asList(
            new Bridge(0, 1),
            new Bridge(2, 3),
            new Bridge(3, 4)
        )).getIncludedBridges());
    }
}

打印

[[0,1], [1,2], [2,3], [3,4]]
[[0,1], [1,2]]
[[0,1]]

【讨论】:

  • 谢谢!方法“bridge.hasSameS(...)”究竟做了什么???你怎么知道哈根? =D
  • 我做过同样的项目(我想那是大约 2 年前的事了),听起来很熟悉(我知道它现在又是课程的主题)。 hasSameS() 只检查两个桥是否有一个共同的岛。它确实检查任何组合 s1-s2。 s1-s1, s2-s1, s2-s2 PS.:我有一个完全不同的方法,我永远不需要像上面的代码这样的东西。但只要它对你有用,我就很高兴。
【解决方案3】:

用 HashMap 试试这个解决方案

public class BridgeSolution {

    public static void main(String[] args) {

        Map<Integer, Integer> bridgeMap = new HashMap<>();

        List<Integer[]> bridges = new ArrayList<>();
        bridges.add(new Integer[]{0, 1});
        bridges.add(new Integer[]{1, 2});
        bridges.add(new Integer[]{2, 3});
        bridges.add(new Integer[]{3, 4});


        for (int i = 0; i < bridges.size(); i++) {
            bridgeMap.put(bridges.get(i)[0], bridges.get(i)[1]);
        }

        Integer start = bridges.get(0)[0];

        Integer value = null;
        Integer sum = start;
        while ((value = bridgeMap.get(start)) != null) {
            sum += value;
            start = value;
        }

        System.out.println(sum);
    }
}

【讨论】:

    【解决方案4】:

    具有以下类:

    public class Graph<V> {
        private static class Edge<VV> {
            private final VV from;
            private final VV to;
    
            private Edge(VV from, VV to) {
                this.from = from;
                this.to = to;
            }
        }
    
        private final Set<V> vertices = new HashSet<>();
        private final Collection<Edge<V>> edges = new ArrayList<>();
    
        public void addEdge(V from, V to) {
            vertices.add(from);
            vertices.add(to);
            edges.add(new Edge(from, to));
        }
    
    
        public Set<V> closure(V start) {
            Set<V> result = new HashSet<>();
            closure(start, result);
            return result;
        }
    
        private void closure(V start, Set<V> seen) {
            if (vertices.contains(start) && !seen.contains(start)) {
                seen.add(start);
                for (Edge<V> e: edges) {
                    if (start.equals(e.from)) {
                        closure(e.to, seen);
                    }
                }
            }
        }
    }
    

    你可以这样做:

        Graph<Integer> graph = new Graph<>();
        graph.addEdge(0,1);
        graph.addEdge(1,2);
        graph.addEdge(3,4);
        int sum = 0;
        for (int v: graph.closure(0)) {
            System.out.println("Vertex: " + v);
            sum += v;
        }
        System.out.println("Sum: " + sum);
    

    输出如下:

    Vertex: 0
    Vertex: 1
    Vertex: 2
    Sum: 3
    

    【讨论】:

      【解决方案5】:

      试试下面的。更改 Bridge 对象以满足您的要求

      public class Bridge {
          int start;
          int end;
      
          public Bridge(int start, int end) {
              this.start = start;
              this.end = end;
          }
      
          public int getStart() {
              return start;
          }
      
          public int getEnd() {
              return end;
          }
      }
      

      计算总和

      import java.io.IOException;
      import java.util.ArrayList;
      import java.util.List;
      
      public class BridgeSum {
          public static void main(String... args) throws IOException {
              Bridge B1 = new Bridge(0, 1);
              Bridge B2 = new Bridge(1, 2);
              Bridge B3 = new Bridge(2, 4);
              Bridge B4 = new Bridge(4, 8);
              Bridge B5 = new Bridge(8, 9);
      
              List<Bridge> list = new ArrayList<>();
              list.add(B5);
              list.add(B2);
              list.add(B3);
              list.add(B1);
              list.add(B4);
      
              list.sort((a, b) -> a.getStart() > b.getStart() ? 0 : -1);
      
              int sum = 0;
              for (int i = 0; i < list.size(); i++) {
                  if (i == 0) {
                      sum = sum + list.get(i).getStart() + list.get(i).getEnd();
                  } else {
                      if (list.get(i).getStart() == list.get(i - 1).getEnd()) {
                          sum = sum + list.get(i).getEnd();
                      } else {
                          break;
                      }
                  }
              }
      
              System.out.println(sum);
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2020-12-18
        • 2014-02-11
        • 2013-04-08
        • 2013-05-26
        • 1970-01-01
        • 2021-09-15
        • 1970-01-01
        • 2017-04-28
        • 2016-08-19
        相关资源
        最近更新 更多