部分leetcode題目

一:

假設按照升序排序的數組在預先未知的某個點上進行了旋轉。
( 例如,數組 [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;
    }
 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章