一:
假設按照升序排序的數組在預先未知的某個點上進行了旋轉。
( 例如,數組 [0,1,2,4,5,6,7] 可能變爲 [4,5,6,7,0,1,2] )。
搜索一個給定的目標值,如果數組中存在這個目標值,則返回它的索引,否則返回 -1 。
你可以假設數組中不存在重複的元素。
你的算法時間複雜度必須是 O(log n) 級別。
示例 1:輸入: nums = [4,5,6,7,0,1,2], target = 0
輸出: 4
示例 2:輸入: nums = [4,5,6,7,0,1,2], target = 3
輸出: -1
public class SearchInRotatedSortedArray {
public int search(int[] nums, int target) {
if (nums == null || nums.length <= 0) {
return -1;
}
int len = nums.length;
int start = 0;
int end = len - 1;
while (start <= end) {
int mid = (start + end) >> 1;
if (nums[mid] == target) {
return mid;
} else if (nums[mid] > target){
// mid在左側遞增大區間
if (nums[mid] > nums[end]) {
// 目標值大於最右側值,左側尋找
if (target > nums[end]) {
end = mid - 1;
// 否則右側尋找
} else {
start = mid + 1;
}
// mid在小區間, 此時mid又大於target,向左側尋找
} else {
end = mid - 1;
}
} else {
// mid在左側遞增大區間
if (nums[mid] > nums[end]) {
// 右側尋找
start = mid + 1;
// mid在小區間, 此時mid又小於target
} else {
if (target > nums[end]) {
// 左側尋找
end = mid - 1;
// 否則右側尋找
} else {
start = mid + 1;
}
}
}
}
return -1;
}
public static void main(String[] args) {
int[] nums = {4,5,6,7,0,1,2};
System.out.println(new SearchInRotatedSortedArray().search(nums, 0));
System.out.println(new SearchInRotatedSortedArray().search(nums, 3));
}
}
題目二:Java實現LRU緩存
方法1:LRU Cache的LinkedHashMap實現
public class LRUCache3<K, V> { private final int MAX_CACHE_SIZE; private final float DEFAULT_LOAD_FACTOR = 0.75f; LinkedHashMap<K, V> map; public LRUCache3(int cacheSize) { MAX_CACHE_SIZE = cacheSize; //根據cacheSize和加載因子計算hashmap的capactiy,+1確保當達到cacheSize上限時不會觸發hashmap的擴容, int capacity = (int) Math.ceil(MAX_CACHE_SIZE / DEFAULT_LOAD_FACTOR) + 1; map = new LinkedHashMap(capacity, DEFAULT_LOAD_FACTOR, true) { @Override protected boolean removeEldestEntry(Map.Entry eldest) { return size() > MAX_CACHE_SIZE; } }; } public synchronized void put(K key, V value) { map.put(key, value); } public synchronized V get(K key) { return map.get(key); } public synchronized void remove(K key) { map.remove(key); } public synchronized Set<Map.Entry<K, V>> getAll() { return map.entrySet(); } public synchronized int size() { return map.size(); } public synchronized void clear() { map.clear(); } @Override public String toString() { StringBuilder sb = new StringBuilder(); for (Map.Entry entry : map.entrySet()) { sb.append(String.format("%s:%s ", entry.getKey(), entry.getValue())); } return sb.toString(); } }
方法2:LRU Cache的鏈表+HashMap實現
public class LRUCache1<K, V> { private final int MAX_CACHE_SIZE; private Entry first; private Entry last; private HashMap<K, Entry<K, V>> hashMap; public LRUCache1(int cacheSize) { MAX_CACHE_SIZE = cacheSize; hashMap = new HashMap<K, Entry<K, V>>(); } public void put(K key, V value) { Entry entry = getEntry(key); if (entry == null) { if (hashMap.size() >= MAX_CACHE_SIZE) { hashMap.remove(last.key); removeLast(); } entry = new Entry(); entry.key = key; } entry.value = value; moveToFirst(entry); hashMap.put(key, entry); } public V get(K key) { Entry<K, V> entry = getEntry(key); if (entry == null) return null; moveToFirst(entry); return entry.value; } public void remove(K key) { Entry entry = getEntry(key); if (entry != null) { if (entry.pre != null) entry.pre.next = entry.next; if (entry.next != null) entry.next.pre = entry.pre; if (entry == first) first = entry.next; if (entry == last) last = entry.pre; } hashMap.remove(key); } private void moveToFirst(Entry entry) { if (entry == first) return; if (entry.pre != null) entry.pre.next = entry.next; if (entry.next != null) entry.next.pre = entry.pre; if (entry == last) last = last.pre; if (first == null || last == null) { first = last = entry; return; } entry.next = first; first.pre = entry; first = entry; entry.pre = null; } private void removeLast() { if (last != null) { last = last.pre; if (last == null) first = null; else last.next = null; } } private Entry<K, V> getEntry(K key) { return hashMap.get(key); } @Override public String toString() { StringBuilder sb = new StringBuilder(); Entry entry = first; while (entry != null) { sb.append(String.format("%s:%s ", entry.key, entry.value)); entry = entry.next; } return sb.toString(); } class Entry<K, V> { public Entry pre; public Entry next; public K key; public V value; } }
題目三:
* 給定一個非空的整數數組,返回其中出現頻率前 k 高的元素。
* 示例 1:
* 輸入: nums = [1,1,1,2,2,3], k = 2
* 輸出: [1,2]
* 示例 2:
* 輸入: nums = [1], k = 1
* 輸出: [1]
* 說明:
* 你可以假設給定的 k 總是合理的,且 1 ≤ k ≤ 數組中不相同的元素的個數。
* 你的算法的時間複雜度必須優於 O(n log n) , n 是數組的大小。
方法1優先隊列(利用優先隊列進行排序,排序到第k個值之後,每次都取頭上的最小數值跟剩下的依次比較,如果比最小的大就放入優先隊列中。注意優先隊列一直保持爲k個數值)
public List<Integer> topKFrequent(int[] nums, int k) {
final HashMap<Integer, Integer> map = new HashMap<>();
//用map統計各個元素都有多少個
for (int num : nums) {
if (map.containsKey(num)) {
map.put(num, map.get(num) + 1);
} else {
map.put(num, 1);
}
}
//用優先隊列獲得最多的前K個
PriorityQueue<Integer> queue = new PriorityQueue<>(new Comparator<Integer>() {
public int compare(Integer a, Integer b) {
// 出現次數少的在前
return map.get(a) - map.get(b);
}
});
for (int key : map.keySet()) {
// 控制隊列元素數量
if (queue.size() < k) {
queue.add(key);
continue;
}
// 隊列中元素達到 K 值 ,去除最小值比較
int small = queue.peek();
if (map.get(small) < map.get(key)) {
queue.poll();
queue.add(key);
}
}
return new ArrayList<Integer>(queue);
}
方法2:桶排序(以數組中某個數字的個數作爲bucket的index)
public List<Integer> topKFrequent2(int[] nums, int k) {
HashMap<Integer, Integer> map = new HashMap<>();
for (int num : nums) {
if (map.containsKey(num)) {
map.put(num, map.get(num) + 1);
} else {
map.put(num, 1);
}
}
// 創建 nums.length + 1 個桶
List<Integer>[] bucket = new List[nums.length + 1];
// 遍歷map,根據value值 出現的次數 放到對應的桶中
for (Map.Entry<Integer, Integer> e : map.entrySet()) {
Integer value = e.getValue();
if (bucket[value] == null) {
bucket[value] = new ArrayList<>();
}
bucket[value].add(e.getKey());
}
List<Integer> freList = new ArrayList<>();
// 桶的編號表示出現次數,所以倒數桶
for (int j = bucket.length - 1; j > -1 && freList.size() < k; j--) {
if (bucket[j] != null)
freList.addAll(bucket[j]);
}
return freList;
}