目录
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];
}
}