1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| class FirstUnique { static class Node { int val; Node prev; Node next;
Node(int _val) { this.val = _val; prev = null; next = null; } }
private void removeNode(Node node) { Node prevNode = node.prev; Node nextNode = node.next; if (prevNode == null && nextNode == null) { head = null; tail = null; } else if (prevNode == null) { head = nextNode; head.prev = null; } else if (nextNode == null) { tail = prevNode; tail.next = null; } else { prevNode.next = nextNode; nextNode.prev = prevNode; } node.prev = null; node.next = null; }
private void insertNode(Node node) { if (head == null) { head = node; tail = node; } else { tail.next = node; node.prev = tail; tail = node; } }
private Node head; private Node tail; private Map<Integer, Node> nodeMap; private Set<Integer> duplicates;
public FirstUnique(int[] nums) { nodeMap = new HashMap<>(); duplicates = new HashSet<>(); for (int num : nums) { add(num); } }
public int showFirstUnique() { if (nodeMap.isEmpty()) { return -1; } return head.val; }
public void add(int value) { Node head = this.head; Node tail = this.tail; Map<Integer, Node> nodeMap = this.nodeMap; if (nodeMap.containsKey(value)) { removeNode(nodeMap.get(value)); nodeMap.remove(value); duplicates.add(value); } else if (!duplicates.contains(value)) { Node newNode = new Node(value); nodeMap.put(value, newNode); insertNode(newNode); } head = this.head; tail = this.tail; } }
|
bug找了好久.25行, tail转移的时候要把新的tail的next声明为null才行. 22行新head要把自己的prev设置为null. 否则就会出错. 比如移除最后一个node时, 新tail还指向旧的node, 这会让remove的逻辑出错, 误以为我们此时的tail不是tail, head的prev如果不指向null也会有一样的问题.
时间复杂度: O(1)
空间复杂度: O(n) 需要存nodes, map以及set.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| class FirstUnique { Set<Integer> unique; Set<Integer> multiple;
public FirstUnique(int[] nums) { unique = new LinkedHashSet<>(); multiple = new HashSet<>(); for (int num : nums) { add(num); } }
public int showFirstUnique() { return unique.isEmpty() ? -1 : unique.iterator().next(); }
public void add(int value) { if (unique.contains(value)) { unique.remove(value); multiple.add(value); } else if (!multiple.contains(value)) { unique.add(value); } } }
|
LinkedHashSet的写法.
时间复杂度和空间复杂度不变.