leetcode hot 100(刷题篇8)(232/88/451/offer10/offer22/344/offer40/494/135/97)

目录

1.leetcode232用栈实现队列

2.leetcode88合并两个有序数组

3.leetcode451根据字符出现频率排序

4.剑指offer10青蛙跳台阶问题

5.剑指offer22链表中环的入口节点

6.leetcode344反转字符串

7.剑指offer40最小的k个数

8.leetcode494目标和

9.leetcode135分发糖果

10.leetcode97交错字符串


1.leetcode232用栈实现队列

/**
        时间复杂度均为O(1)
 */
class MyQueue {
    Deque<Integer> inStack;
    Deque<Integer> outStack;

    public MyQueue() {
        inStack = new ArrayDeque<Integer>();
        outStack = new ArrayDeque<Integer>();
    }

    public void push(int x) {
        inStack.push(x);
    }

    public int pop() {
        if (outStack.isEmpty()) {
            in2out();
        }
        return outStack.pop();
    }

    public int peek() {
        if (outStack.isEmpty()) {
            in2out();
        }
        return outStack.peek();
    }

    public boolean empty() {
        return inStack.isEmpty() && outStack.isEmpty();
    }

    private void in2out() {
        while (!inStack.isEmpty()) {
            outStack.push(inStack.pop());
        }
    }
}

2.leetcode88合并两个有序数组

/**
    时间复杂度O( M * N )
 */
class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        int p1 = 0, p2 = 0;
        int[] sorted = new int[m + n];
        int cur;
        while (p1 < m || p2 < n) {
            if (p1 == m) {
                cur = nums2[p2++];
            } else if (p2 == n) {
                cur = nums1[p1++];
            } else if (nums1[p1] < nums2[p2]) {
                cur = nums1[p1++];
            } else {
                cur = nums2[p2++];
            }
            sorted[p1 + p2 - 1] = cur;
        }
        for (int i = 0; i != m + n; ++i) {
            nums1[i] = sorted[i];
        }
    }
}

3.leetcode451根据字符出现频率排序

/**
    时间复杂度O( M + N)   一个字符串的长   一个字符串不一样的字符数

    基数排序的思想
 */
class Solution {
    public String frequencySort(String s) {
        //Hashmap 存储每个字符出现的次数,并且获得次数最多的。
        Map<Character, Integer> map = new HashMap<Character, Integer>();
        int maxFreq = 0;
        int length = s.length();
        for (int i = 0; i < length; i++) {
            char c = s.charAt(i);
            int frequency = map.getOrDefault(c, 0) + 1;
            map.put(c, frequency);
            maxFreq = Math.max(maxFreq, frequency);
        }
        //创建次数最多的数量对应的buckets桶
        StringBuffer[] buckets = new StringBuffer[maxFreq + 1];
        for (int i = 0; i <= maxFreq; i++) {
            buckets[i] = new StringBuffer();
        }
        // 循环赋值
        // 代表 次数  字母
        for (Map.Entry<Character, Integer> entry : map.entrySet()) {
            char c = entry.getKey();
            int frequency = entry.getValue();
            buckets[frequency].append(c);
        }
        //写入到sb中
        StringBuffer sb = new StringBuffer();
        for (int i = maxFreq; i > 0; i--) {  //从大到小开始写入
            StringBuffer bucket = buckets[i];  //获取对应字母
            int size = bucket.length();  //对应字母的个数
            for (int j = 0; j < size; j++) { // 遍历字母的个数
                for (int k = 0; k < i; k++) { //每个字母写入对应的次数
                    sb.append(bucket.charAt(j)); //写入
                }
            }
        }
        return sb.toString();
    }
}

4.剑指offer10青蛙跳台阶问题

/**
    时间复杂度O(N)
        大数越界: 随着 n 增大, f(n) 会超过 Int32 甚至 Int64 的取值范围,导致最终的返回值错误。
             最小的十位质数1000000007
         1000000007 是最小的十位质数。模1000000007,可以保证值永远在int的范围内。
 */
class Solution {
    public int numWays(int n) {
        if (n == 0 || n == 1) {
            return 1;
        }
        int[] dp = new int[n + 1];
        dp[1] = 1;
        dp[2] = 2;
        for (int i = 3; i <= n; i++) {
            dp[i] = (dp[i - 2] + dp[i - 1]) % 1000000007;
        }
        return dp[n];
    }
}

5.剑指offer22链表中环的入口节点

/**
    时间复杂度O(N)
 */
class Solution {
    public ListNode detectCycle(ListNode head) {
        if (head == null) {
            return null;
        }
        ListNode slow = head, fast = head;
        while (fast != null) {
            slow = slow.next;
            if (fast.next != null) {
                fast = fast.next.next;
            } else {
                return null;
            }
            if (fast == slow) {
                ListNode ptr = head;
                while (ptr != slow) {
                    ptr = ptr.next;
                    slow = slow.next;
                }
                return ptr;
            }
        }
        return null;
    }
}

6.leetcode344反转字符串

/**
    时间复杂度O(N)
    双指针来实现
 */
class Solution {
    public void reverseString(char[] s) {
        int n = s.length;
        for (int left = 0, right = n - 1; left < right; ++left, --right) {
            char tmp = s[left];
            s[left] = s[right];
            s[right] = tmp;
        }
    }
}

7.剑指offer40最小的k个数

/**
    时间复杂度O( n logn)
    空间复杂度O(logn)
*/
class Solution {
    public int[] getLeastNumbers(int[] arr, int k) {
        int[] vec = new int[k];
        Arrays.sort(arr);
        for (int i = 0; i < k; ++i) {
            vec[i] = arr[i];
        }
        return vec;
    }
}



/**
    时间复杂度O( n logk)
    空间复杂度O(k)
*/
class Solution {
    public int[] getLeastNumbers(int[] arr, int k) {
        int[] vec = new int[k];
        if (k == 0) { // 排除 0 的情况
            return vec;
        }
        PriorityQueue<Integer> queue = new PriorityQueue<Integer>(new Comparator<Integer>() {
            public int compare(Integer num1, Integer num2) {
                return num2 - num1;  //变成大根堆
            }
        });
        for (int i = 0; i < k; ++i) {
            queue.offer(arr[i]);
        }
        for (int i = k; i < arr.length; ++i) {
            if (queue.peek() > arr[i]) {
                queue.poll();     // peek > arr[i]   也就是i小  就写入  
                queue.offer(arr[i]);
            }
        }
        //小就写入,此时我大根堆维护的是最小的k个数
        for (int i = 0; i < k; ++i) {
            vec[i] = queue.poll();
        }
        return vec;
    }
}


/**
    时间复杂度O( n )
    空间复杂度O( logn )
*/
class Solution {
    public int[] getLeastNumbers(int[] arr, int k) {
        randomizedSelected(arr, 0, arr.length - 1, k);
        int[] vec = new int[k];
        for (int i = 0; i < k; ++i) {
            vec[i] = arr[i];
        }
        return vec;
    }

    private void randomizedSelected(int[] arr, int l, int r, int k) {
        if (l >= r) {
            return;
        }
        int pos = randomizedPartition(arr, l, r);
        int num = pos - l + 1;
        if (k == num) {  //如果返回的一侧,正好等于k,那么正好左边是最小的k个数
            return;   //如果返回的一侧,正好等于k,那么正好左边是最小的k个数
        } else if (k < num) {  // 否则
            randomizedSelected(arr, l, pos - 1, k);
        } else { //否则
            randomizedSelected(arr, pos + 1, r, k - num);
        }
    }

    // 基于随机的划分
    private int randomizedPartition(int[] nums, int l, int r) {
        int i = new Random().nextInt(r - l + 1) + l;
        swap(nums, r, i);
        return partition(nums, l, r);
    }

    private int partition(int[] nums, int l, int r) {
        int pivot = nums[r];
        int i = l - 1;
        for (int j = l; j <= r - 1; ++j) {
            if (nums[j] <= pivot) {
                i = i + 1;
                swap(nums, i, j);
            }
        }
        swap(nums, i + 1, r);
        return i + 1;   //返回一次的index
    }

    private void swap(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}

8.leetcode494目标和

/**
    时间复杂度O(2的n次方)
*/
class Solution {
        public static int findTargetSumWays(int[] arr, int s) {
        return process1(arr, 0, s);
    }
 
 
    public static int process1(int[] arr, int index, int rest) {
        if (index == arr.length) { 
            return rest == 0 ? 1 : 0;
        }
 
        return process1(arr, index + 1, rest - arr[index]) + process1(arr, index + 1, rest + arr[index]);
    }
}


/**
    记忆化搜索
*/
class Solution {
    public static int findTargetSumWays(int[] arr, int s) {
        return process2(arr, 0, s, new HashMap<>());
    }
    //HashMap<Integer, HashMap<Integer, Integer>> dp
    // index + rest
    // index == 7 rest = 13   256
    // index == 7 rest = 35   17
    //{index   rest  ans
    //	7 :  { 13 , 256}
    //	  :  { 35 , 17}
    //}
    public static int process2(int[] arr, int index, int rest, HashMap<Integer, HashMap<Integer, Integer>> dp) {
        if (dp.containsKey(index) && dp.get(index).containsKey(rest)) {
            return dp.get(index).get(rest);
        }
        // 否则,没命中!
        int ans = 0;
        if (index == arr.length) {
            ans = rest == 0 ? 1 : 0;
        } else {
            ans = process2(arr, index + 1, rest - arr[index], dp) + process2(arr, index + 1, rest + arr[index], dp);
        }
        if (!dp.containsKey(index)) {
            dp.put(index, new HashMap<>());
        }
        dp.get(index).put(rest, ans);
        return ans;
    }
}

9.leetcode135分发糖果

/**
       时间复杂度O(N)
        空间复杂度O(N)
*/
class Solution {
        // 这是原问题的优良解
    // 时间复杂度O(N),额外空间复杂度O(N)
    public static int candy(int[] arr) {
        if (arr == null || arr.length == 0) {
            return 0;
        }
        int N = arr.length;
        int[] left = new int[N];
        for (int i = 1; i < N; i++) {
            if (arr[i - 1] < arr[i]) {
                left[i] = left[i - 1] + 1;
            }
        }
        int[] right = new int[N];
        for (int i = N - 2; i >= 0; i--) {
            if (arr[i] > arr[i + 1]) {
                right[i] = right[i + 1] + 1;
            }
        }
        int ans = 0;
        for (int i = 0; i < N; i++) {
            ans += Math.max(left[i], right[i]);
        }
        return ans + N;
    }
}

10.leetcode97交错字符串

/**
    时间复杂度 O( m n )
    空间复杂度 O( m n )
*/
class Solution {
    public static boolean isInterleave(String s1, String s2, String s3) {
        if (s1 == null || s2 == null || s3 == null) {
            return false;
        }
        char[] str1 = s1.toCharArray();
        char[] str2 = s2.toCharArray();
        char[] str3 = s3.toCharArray();
        if (str3.length != str1.length + str2.length) {
            return false;
        }
        boolean[][] dp = new boolean[str1.length + 1][str2.length + 1];
        dp[0][0] = true;
        for (int i = 1; i <= str1.length; i++) {
            if (str1[i - 1] != str3[i - 1]) {
                break;
            }
            dp[i][0] = true;
        }
        for (int j = 1; j <= str2.length; j++) {
            if (str2[j - 1] != str3[j - 1]) {
                break;
            }
            dp[0][j] = true;
        }
        for (int i = 1; i <= str1.length; i++) {
            for (int j = 1; j <= str2.length; j++) {
                if (
                        (str1[i - 1] == str3[i + j - 1] && dp[i - 1][j])
                                ||
                                (str2[j - 1] == str3[i + j - 1] && dp[i][j - 1])
                ) {
                    dp[i][j] = true;
                }
            }
        }
        return dp[str1.length][str2.length];
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值