概述
文章目录
- Date Structure Note Part.1
- Big O notation: Runtime Complexity
- Space complexity
- Lists
- Arrays
- operation
- Build an Array
- LinkedList
- Overview of Linked Lists
- Runtime Complexity
- Build a Linked List
- Array VS LinkedList
- Quick
- Compare runtime complexity
- Interview Question
- Stack
- What can use for
- Feature: LIFO (Last in First out)
- Operations
- Interview Question
- Build a Stack
- Queues
- What can use for
- Feature: FIFO (First in First out)
- Operations
- Interview Question
- Build a Queue
- Build a Priority Queue (Default: min Heap)
- Hash Tables
- What can use for
- Operations
- Interview Question
- Hash Function
- Collisions
- Build a Hash Table
Date Structure Note Part.1
Big O notation: Runtime Complexity
- O(1): constance
- O(n): related to the input size
- O(n^2): O(n * n) very slow
- O(log n): very fast
- O(2^n): very very slow
Sort: O(1) > O(log n) > O(n) > O(n^2) > O(2^n)
Space complexity
- O(1) : constance
- O(n): related to the input size
Lists
Arrays
operation
- Lookup by Index: O(1)
- Lookup by Value: O(n)
- Insert: O(n)
- Delete: O(n)
Build an Array
package Arrays;
public class Main {
public static void main(String[] args) {
Array numbers = new Array(3);
numbers.insert(10);
numbers.insert(20);
numbers.insert(30);
numbers.insert(40);
numbers.removeAt(3);
System.out.println(numbers.indexOf(100));
}
}
package Arrays;
public class Array {
private int[] array;
private int lastIndex = -1;
public Array(int length) {
array = new int[length];
}
public void insert(int item) {
if (lastIndex + 1 >= array.length) resize();
array[++lastIndex] = item;
}
public int removeAt(int index) {
if (index > lastIndex) return -1;
int result = array[index];
for (int i = index + 1; i <= lastIndex; i++)
array[i - 1] = array[i];
lastIndex--;
return result;
}
public int indexOf(int item) {
for (int i = 0; i <= lastIndex; i++)
if (array[i] == item) return i;
return -1;
}
private void resize() {
int[] newArray = new int[array.length * 2];
// O(n)
for (int i = 0; i < array.length; i++)
newArray[i] = array[i];
array = newArray;
}
}
LinkedList
Overview of Linked Lists
- view: Head -> Node -> … -> Tail
- Structure: Value nextNode
Runtime Complexity
- Insert: At the End: O(1); At the Beginning: O(1); In the Middle: O(n);
- Delete: From the End: O(n); From the Beginning: O(1); From the Middle: O(n);
Build a Linked List
package Arrays;
public class Main {
public static void main(String[] args) {
LinkedList numbers = new LinkedList();
numbers.addFirst(10);
numbers.addFirst(20);
numbers.addFirst(30);
numbers.addFirst(40);
numbers.deleteFirst();
System.out.println(numbers.toString());
System.out.println(numbers.indexOf(100));
}
package LinkedList;
import java.util.Arrays;
import java.util.NoSuchElementException;
public class LinkedList {
private class Node {
private int value;
private Node next;
public Node(int value) {
this.value = value;
}
}
private Node first;
private Node last;
private int size = 0;
public void addFirst(int item) {
if (isEmpty()) first = last = new Node(item);
else {
Node node = new Node(item);
node.next = first;
first = node;
}
size++;
}
public void addLast(int item) {
if (isEmpty()) first = last = new Node(item);
else {
Node node = new Node(item);
last.next = node;
last = node;
}
size++;
}
public void deleteFirst() {
if (isEmpty()) throw new NoSuchElementException();
if (size == 1)
first = last = null;
else {
Node temp = first;
first = first.next;
temp.next = null;
}
size--;
}
public void deleteLast() {
if (isEmpty()) throw new NoSuchElementException();
if (size == 1)
first = last = null;
else {
Node previous = getPrevious(last);
last = previous;
previous.next = null;
}
size--;
}
private Node getPrevious(Node node) {
Node current = first;
while (current != null && current.next != node)
current = current.next;
return null;
}
public int indexOf(int item) {
int index = -1;
Node current = first;
for (int i = 0; i < size; i++) {
if (current.value == item) index = i;
current = current.next;
}
return index;
}
public boolean contains(int item) {
return indexOf(item) != -1;
}
public int size() {
return size;
}
public boolean isEmpty() {
return first == null || last == null;
}
@Override
public String toString() {
Node current = first;
int[] output = new int[size];
for (int i = 0; i < size; i++) {
output[i] = current.value;
current = current.next;
}
return Arrays.toString(output);
}
}
Array VS LinkedList
Quick
- Static arrays have a fixed size
- Dynamic arrays grow by 50-100%
- Linked lists don’t waste memory
- Use arrays if you know the number of items to store
- new ArrayList(100)
Compare runtime complexity
Lookup Arrays LinkedList
By Index O(1) O(n)
By Value O(n) O(n)
Insert
Beginning/End O(n) O(1)
Middle O(n) O(n)
Delete
Beginning O(n) O(1)
Middle O(n) O(n)
End O(n) O(n)/O(1) -> double linked list
Interview Question
-
Reverse a linked list. (three pointer)
eg. [10, 20, 30] -> [30, 20, 10]
public void reverse() {
if (isEmpty()) return;
Node previous = first;
Node current = first.next;
while (current != null) {
Node next = current.next;
current.next = previous;
previous = current;
current = next;
}
last = first;
last.next = null;
first = previous;
}
-
Find the Kth node from the end of a linked list in one pass. (two pointer)
eg. [10, 20, 30, 40, 50] k=1(50); k=2(40)…
public int getKthFromTheEnd(int k) {
int distance = k - 1;
if (distance > size || k <= 0) throw new IllegalArgumentException();
Node left = first, right = first;
for (int i = 0; i < distance; i++)
right = right.next;
while (right.next != null) {
left = left.next;
right = right.next;
}
return left.value;
}
Stack
What can use for
- Implement the undo feature
- Build compilers
- Evaluate expressions
- Build navigation
Feature: LIFO (Last in First out)
Operations
- push(item) O(1)
- pop() O(1)
- peek() O(1)
- isEmpty() O(1)
Interview Question
-
Reversing a sting. (implement by stack)
eg. “abcd” -> “dcba”
public String reverse(String str) {
if (str == null) throw new IllegalArgumentException();
Stack<Character> stack = new Stack<>();
StringBuilder stringBuilder = new StringBuilder();
for (char ch : str.toCharArray())
stack.add(ch);
while (!stack.isEmpty())
stringBuilder.append(stack.pop());
return stringBuilder.toString();
}
-
Is string balanced.
eg. “(1 + 1)” is balance; "(1 + " is not balance.
public static boolean isbalanced(String input) {
if (input == null) throw new IllegalArgumentException();
Stack<Character> leftBrace = new Stack<>();
Stack<Character> rightBrace = new Stack<>();
for (char ch : input.toCharArray())
if (
ch == '{' ||
ch == '[' ||
ch == '(' ||
ch == '<' ||
ch == '>' ||
ch == ')' ||
ch == ']' ||
ch == '}')
leftBrace.push(ch);
while (!leftBrace.isEmpty()) {
char ch = leftBrace.peek();
if (
ch == '>' ||
ch == ')' ||
ch == ']' ||
ch == '}') {
rightBrace.add(leftBrace.pop());
continue;
}
if (ch == '<')
if (rightBrace.isEmpty() || rightBrace.peek() != '>')
return false;
if (ch == '(')
if (rightBrace.isEmpty() || rightBrace.peek() != ')')
return false;
if (ch == '[')
if (rightBrace.isEmpty() || rightBrace.peek() != ']')
return false;
if (ch == '{')
if (rightBrace.isEmpty() || rightBrace.peek() != '}')
return false;
rightBrace.pop();
leftBrace.pop();
}
return rightBrace.isEmpty();
}
private final List<Character> leftBrackets = Arrays.asList('{', '[', '(', '<');
private final List<Character> rightBrackets = Arrays.asList('}', ']', ')', '>');
public boolean isbalanced(String input) {
Stack<Character> stack = new Stack<>();
for (char ch : input.toCharArray()) {
if (isLeftBracket(ch))
stack.push(ch);
if (isRightBracket(ch)) {
if (stack.empty()) return false;
char top = stack.pop();
if (bracketsMatch(top, ch)) return false;
}
}
return true;
}
private boolean isLeftBracket(char ch) {
return leftBrackets.contains(ch);
}
private boolean isRightBracket(char ch) {
return rightBrackets.contains(ch);
}
private boolean bracketsMatch(char left, char right) {
return leftBrackets.indexOf(left) == rightBrackets.indexOf(right);
}
Build a Stack
import Stack.Stack;
public class Main {
public static void main(String[] args) {
Stack stack = new Stack();
stack.push(1);
stack.push(2);
stack.push(3);
stack.push(4);
stack.push(5);
int res = stack.pop();
System.out.println(res);
System.out.println(stack);
}
}
package Stack;
import java.util.Arrays;
import java.util.EmptyStackException;
public class Stack {
private int[] items;
private int count = 0;
public Stack() {
items = new int[10];
}
public void push(int item) {
if (count == items.length) throw new StackOverflowError();
items[count++] = item;
}
public int pop() {
if (count == 0) throw new EmptyStackException();
return items[--count];
}
public int peek() {
if (count == 0) throw new EmptyStackException();
return items[count - 1];
}
public boolean isEmpty() {
return count == 0;
}
@Override
public String toString() {
int[] content = Arrays.copyOfRange(items, 0, count);
return Arrays.toString(content);
}
}
Queues
What can use for
- resources management
- printers
- operating systems
- web serbers
- live support systems
Feature: FIFO (First in First out)
Operations
- enqueue O(1) PriorityQueue: enqueue O(n)
- dequeue O(1)
- peek O(1)
- isEmpty O(1)
- isFull O(1)
Interview Question
- reverse a queue. (only allow using addremoveisEmpty)
public void reverse(Queue<Integer> queue) {
Stack<Integer> stack = new Stack<>();
while (!queue.isEmpty())
stack.push(queue.remove());
while (!stack.isEmpty())
queue.add(stack.pop());
}
- using two stack build a queue
package Queue;
import java.util.Stack;
public class StackQueue {
private Stack<Integer> enqueue = new Stack<>();
private Stack<Integer> dequeue = new Stack<>();
public void add(int item) {
enqueue.add(item);
}
public int remove() {
if (isEmpty()) throw new IllegalStateException();
moveEnqueueStackToDequeueStack();
return dequeue.pop();
}
public int peek() {
if (isEmpty()) throw new IllegalStateException();
moveEnqueueStackToDequeueStack();
return dequeue.peek();
}
private void moveEnqueueStackToDequeueStack() {
if (dequeue.isEmpty())
while (!enqueue.isEmpty())
dequeue.add(enqueue.pop());
}
private boolean isEmpty() {
return enqueue.isEmpty() && dequeue.isEmpty();
}
}
Build a Queue
package Queue;
import java.util.Arrays;
public class ArrayQueue {
private int[] items = new int[5];
private int front = 0;
private int rear = 0;
private int count;
public void enqueue(int item) {
if (isFull()) throw new IllegalStateException();
items[rear] = item;
rear = (rear + 1) % items.length;
count++;
}
public int dequeue() {
int item = items[front];
items[front++] = 0;
front = (front + 1) % items.length;
count--;
return item;
}
public int peek() {
return items[front];
}
public boolean isEmpty() {
return count == 0;
}
public boolean isFull() {
return count == items.length;
}
@Override
public String toString() {
return Arrays.toString(items);
}
}
Build a Priority Queue (Default: min Heap)
package Queue;
import java.util.Arrays;
public class PriorityQueue {
private int[] items = new int[5];
private int count;
public void add(int item) {
if (isFull()) throw new IllegalStateException();
if (isEmpty()) {
items[count++] =
item;
return;
}
int i = shiftItemsToInsert(item);
items[i] = item;
count++;
}
private int shiftItemsToInsert(int item) {
int i;
for (i = count - 1; i >= 0; i--) {
if (item < items[i])
items[i + 1] = items[i];
else
break;
}
return i + 1;
}
public int remove() {
if (isEmpty()) throw new IllegalStateException();
return items[--count];
}
private boolean isEmpty() {
return count == 0;
}
private boolean isFull() {
return count == items.length;
}
@Override
public String toString() {
return Arrays.toString(items);
}
}
Hash Tables
What can use for
- Spell checkers
- Dictionaries
- Compilers
- Code editors
Operations
- Insert O(1)
- Lookup O(1)
- Delete O(1)
Interview Question
-
Find the first none repeated character.
eg. “A Green Apple” -> ‘G’
public static char findTheFirstNoneRepeatedCharacter(String str) {
str = str.toLowerCase();
Map<Character, Integer> dic = new HashMap<>();
char[] chars = str.toCharArray();
for (char ch : chars) {
if (!dic.containsKey(ch)) dic.put(ch, 1);
else dic.put(ch, dic.get(ch) + 1);
}
for (char ch : chars)
if (dic.get(ch) == 1) return ch;
return ' ';
}
public static char findTheFirstNoneRepeatedCharacter2(String str) {
if (str == null || str.trim() == "") return ' ';
String copy = str.toLowerCase();
Set<Character> repeated = new HashSet<>();
int left = 0, right = 1;
while (right < copy.length() && left < right) {
if (copy.charAt(left) == ' ') left++;
if (copy.charAt(left) != copy.charAt(right)) right++;
else repeated.add(copy.charAt(left++));
}
return left < copy.length()
&& !repeated.contains(copy.charAt(left))
? copy.charAt(left)
: ' ';
}
-
Find the first repeated character.
eg. “green apple” -> ‘e’
public static char findTheFirstRepeatedChar(String str) {
Set<Character> repeated = new HashSet<>();
Set<Character> noneRepeated = new HashSet<>();
char[] chars = str.toLowerCase().toCharArray();
for (char ch : chars) {
if (!noneRepeated.contains(ch)) noneRepeated.add(ch);
else repeated.add(ch);
}
for (char ch : chars)
if (repeated.contains(ch)) return ch;
return ' ';
}
Hash Function
- “1234” -> 10
- If the array size is 5, then mod the result by 5, and we get 0;
- “1234” -> 0;
Collisions
When input two different keys, but we get the same address.
eg. Key1->O->address<-O<-Key2
Solution:
- Channing: eg. Address: ????->Key1->Key2
- Open Addressing:
- Linear Probing: (hash(key) + i) % table_size
- Quadratic Probing: (hash(key) + i^2) % table_size
- Double Hashing:
- hash2(key) = prime - (key % prime);
- index = (hash1(key) + i * hash2(key)) % table_size;
Build a Hash Table
import HashTable.HashTable;
public class Main {
public static void main(String[] args) {
HashTable dic = new HashTable();
dic.put(6, "b");
dic.put(1, "a");
System.out.println(dic.get(1));
}
}
package HashTable;
import java.util.LinkedList;
public class HashTable {
private class Entry {
private int key;
private String value;
public Entry(int key, String value) {
this.key = key;
this.value = value;
}
}
private LinkedList<Entry>[] entries = new LinkedList[5];
public void put(int key, String value) {
Entry entry = getEntry(key);
if (entry != null) {
entry.value = value;
return;
}
getOrCreateBucket(key).add(new Entry(key, value));
}
private int hash(int key) {
return key % entries.length;
}
public String get(int key) {
Entry entry = getEntry(key);
return entry == null ? null : entry.value;
}
public void remove(int key) {
Entry entry = getEntry(key);
if (entry == null) throw new IllegalStateException();
getBucket(key).remove(entry);
}
private Entry getEntry(int key) {
int index = hash(key);
LinkedList<Entry> bucket = entries[index];
if (bucket != null)
for (Entry entry : bucket)
if (entry.key == key)
return entry;
return null;
}
private LinkedList<Entry> getBucket(int key) {
return entries[hash(key)];
}
private LinkedList<Entry> getOrCreateBucket(int key) {
int index = hash(key);
LinkedList<Entry> bucket = entries[index];
if (bucket == null) entries[index] = new LinkedList<>();
return bucket;
}
}
最后
以上就是舒服豆芽为你收集整理的数据结构学习笔记(一) 基础数据结构Date Structure Note Part.1的全部内容,希望文章能够帮你解决数据结构学习笔记(一) 基础数据结构Date Structure Note Part.1所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复