Given a list of airline tickets represented by pairs of departure and arrival airports [from, to]
, reconstruct the itinerary in order. All of the tickets belong to a man who departs from JFK
. Thus, the itinerary must begin with JFK
.
Note:
["JFK", "LGA"]
has a smaller lexical order than ["JFK", "LGB"]
.Example 1:
tickets
= [["MUC", "LHR"], ["JFK", "MUC"], ["SFO", "SJC"], ["LHR", "SFO"]]
Return ["JFK", "MUC", "LHR", "SFO", "SJC"]
.
Example 2:
tickets
= [["JFK","SFO"],["JFK","ATL"],["SFO","ATL"],["ATL","JFK"],["ATL","SFO"]]
Return ["JFK","ATL","JFK","SFO","ATL","SFO"]
.
Another possible reconstruction is ["JFK","SFO","ATL","JFK","ATL","SFO"]
. But it is larger in lexical order.
public class Solution { public String[][] sort(String[][] tickets){ String min0,min1; int index; for(int i=0;i<tickets.length-1;i++){ min0=tickets[i][0]; min1=tickets[i][1]; index=i; for(int j=i+1;j<tickets.length;j++){ if(tickets[j][0].compareTo(min0)<0){ min0=tickets[j][0]; min1=tickets[j][1]; index=j; } else { if(tickets[j][0].compareTo(min0)==0){ if(tickets[j][1].compareTo(min1)<0){ min1=tickets[j][1]; index=j; } } } } if(index!=i){ tickets[index][0]=tickets[i][0]; tickets[index][1]=tickets[i][1]; tickets[i][0]=min0; tickets[i][1]=min1; } } return tickets; } public boolean search(int count,boolean[] use,String[][] tickets,ArrayList<String> path){ if(count==0){ int i; for(i=0;i<tickets.length;i++) if(tickets[i][0].compareTo("JFK")==0) break; for(int j=i;j<tickets.length;j++){ if(tickets[j][0].compareTo("JFK")!=0) break; count++; use[j]=true; path.add(tickets[j][0]); path.add(tickets[j][1]); if(search(count, use, tickets, path)) return true; count--; use[j]=false; path.remove(path.size()-1); path.remove(path.size()-1); } } else { if(count==tickets.length){ return true; } else { int i; for(i=0;i<tickets.length;i++){ if(tickets[i][0].compareTo(path.get(path.size()-1))==0) break; } for(int j=i;j<tickets.length;j++){ if(tickets[j][0].compareTo(tickets[i][0])!=0) break; if(use[j]==false){ use[j]=true; count++; path.add(tickets[j][1]); if(search(count, use, tickets, path)) return true; count--; use[j]=false; path.remove(path.size()-1); } } } } return false; } public ArrayList<String> findItinerary(String[][] tickets) { ArrayList<String> path=new ArrayList<>(); if(tickets.length==0) return path; if(tickets.length==1){ path.add(tickets[0][0]); path.add(tickets[0][1]); return path; } tickets=sort(tickets); boolean[] use=new boolean[tickets.length]; for(int i=0;i<tickets.length;i++) use[i]=false; int count=0; search(count,use,tickets,path); return path; } }
public List<String> findItinerary(String[][] tickets) { for (String[] ticket : tickets) targets.computeIfAbsent(ticket[0], k -> new PriorityQueue()).add(ticket[1]); visit("JFK"); return route; } Map<String, PriorityQueue<String>> targets = new HashMap<>(); List<String> route = new LinkedList(); void visit(String airport) { while(targets.containsKey(airport) && !targets.get(airport).isEmpty()) visit(targets.get(airport).poll()); route.add(0, airport); }
public List<String> findItinerary(String[][] tickets) { Map<String, PriorityQueue<String>> targets = new HashMap<>(); for (String[] ticket : tickets) targets.computeIfAbsent(ticket[0], k -> new PriorityQueue()).add(ticket[1]); List<String> route = new LinkedList(); Stack<String> stack = new Stack<>(); stack.push("JFK"); while (!stack.empty()) { while (targets.containsKey(stack.peek()) && !targets.get(stack.peek()).isEmpty()) stack.push(targets.get(stack.peek()).poll()); route.add(0, stack.pop()); } return route; }
import java.util.Comparator; import java.util.PriorityQueue; import java.util.Queue; public class test { private String name; private int population; public test(String name, int population) { this.name = name; this.population = population; } public String getName() { return this.name; } public int getPopulation() { return this.population; } public String toString() { return getName() + " - " + getPopulation(); } public static void main(String args[]) { Comparator<test> OrderIsdn = new Comparator<test>(){ public int compare(test o1, test o2) { // TODO Auto-generated method stub int numbera = o1.getPopulation(); int numberb = o2.getPopulation(); if(numberb > numbera) { return 1; } else if(numberb<numbera) { return -1; } else { return 0; } } }; Queue<test> priorityQueue = new PriorityQueue<test>(11,OrderIsdn); test t1 = new test("t1",1); test t3 = new test("t3",3); test t2 = new test("t2",2); test t4 = new test("t4",0); priorityQueue.add(t1); priorityQueue.add(t3); priorityQueue.add(t2); priorityQueue.add(t4); System.out.println(priorityQueue.poll().toString()); } }
Map<Integer, String> map = new HashMap<>(); for (int i = 0; i < 10; i++) { map.putIfAbsent(i, "val" + i); } map.forEach((id, val) -> System.out.println(val));上面的代码风格是完全自解释的:putIfAbsent避免我们将null写入;forEach接受一个消费者对象,从而将操作实施到每一个map中的值上。
map.computeIfPresent(3, (num, val) -> val + num); map.get(3); // val33 map.computeIfPresent(9, (num, val) -> null); map.containsKey(9); // false map.computeIfAbsent(23, num -> "val" + num); map.containsKey(23); // true map.computeIfAbsent(3, num -> "bam"); map.get(3); // val33接下来,我们将学习,当给定一个key值时,如何把一个实例从对应的key中移除:
map.remove(3, "val3"); map.get(3); // val33 map.remove(3, "val33"); map.get(3); // null另一个有用的方法:
map.getOrDefault(42, "not found"); // not found将map中的实例合并也是非常容易的:
map.merge(9, "val9", (value, newValue) -> value.concat(newValue)); map.get(9); // val9 map.merge(9, "concat", (value, newValue) -> value.concat(newValue)); map.get(9); // val9concat合并操作先看map中是否没有特定的key/value存在,如果是,则把key/value存入map,否则merging函数就会被调用,对现有的数值进行修改。
List<String> names = Arrays.asList("peter", "anna", "mike", "xenia"); Collections.sort(names, new Comparator<String>() { @Override public int compare(String a, String b) { return b.compareTo(a); } });静态工具方法Collections.sort接受一个list,和一个Comparator接口作为输入参数,Comparator的实现类可以对输入的list中的元素进行比较。通常情况下,你可以直接用创建匿名Comparator对象,并把它作为参数传递给sort方法。
Collections.sort(names, (String a, String b) -> { return b.compareTo(a); });你可以看到,这段代码就比之前的更加简短和易读。但是,它还可以更加简短
Collections.sort(names, (String a, String b) -> b.compareTo(a));只要一行代码,包含了方法体。你甚至可以连大括号对{}和return关键字都省略不要。不过这还不是最短的写法:
Collections.sort(names, (a, b) -> b.compareTo(a));Java编译器能够自动识别参数的类型,所以你就可以省略掉类型不写。让我们再深入地研究一下lambda表达式的威力吧。
Lambda表达式如何匹配Java的类型系统?每一个lambda都能够通过一个特定的接口,与一个给定的类型进行匹配。一个所谓的函数式接口必须要有且仅有一个抽象方法声明。每个与之对应的lambda表达式必须要与抽象方法的声明相匹配。由于默认方法不是抽象的,因此你可以在你的函数式接口里任意添加默认方法。
任意只包含一个抽象方法的接口,我们都可以用来做成lambda表达式。为了让你定义的接口满足要求,你应当在接口前加上@FunctionalInterface 标注。编译器会注意到这个标注,如果你的接口中定义了第二个抽象方法的话,编译器会抛出异常。
@FunctionalInterface interface Converter<F, T> { T convert(F from); } Converter<String, Integer> converter = (from) -> Integer.valueOf(from); Integer converted = converter.convert("123"); System.out.println(converted); // 123上面的代码实例可以通过静态方法引用,使之更加简洁:
Converter<String, Integer> converter = Integer::valueOf; Integer converted = converter.convert("123"); System.out.println(converted); // 123Java 8 允许你通过::关键字获取方法或者构造函数的的引用。上面的例子就演示了如何引用一个静态方法。而且,我们还可以对一个对象的方法进行引用:
class Something { String startsWith(String s) { return String.valueOf(s.charAt(0)); } } Something something = new Something(); Converter<String, String> converter = something::startsWith; String converted = converter.convert("Java"); System.out.println(converted); // "J"