一、旋转数组

import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* 旋转数组
* @param n int整型 数组长度
* @param m int整型 右移距离
* @param a int整型一维数组 给定数组
* @return int整型一维数组
*/
public int[] solve (int n, int m, int[] a) {
if (m == 0) return a;
m = m % n;
Stack<Integer> one = new Stack<>();
for (int i = 0 ; i < m ; i++) {
one.push(a[a.length - 1 - i]);
}
List<Integer> res = new ArrayList<>();
for (int j = 0; j < m; j++) {
res.add(one.pop());
}
System.arraycopy(a, 0, a, res.size(), a.length - res.size());
for (int k = 0 ; k < res.size(); k++) {
a[k] = res.get(k);
}
return a;
}
}
运行结果

二、螺旋矩阵
给定一个m x n大小的矩阵(m行,n列),按螺旋的顺序返回矩阵中的所有元素。
数据范围:0≤n,m≤10,矩阵中任意元素都满足 ∣val∣≤100
要求:空间复杂度 O(nm),时间复杂度 O(nm)
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param matrix int整型二维数组
* @return int整型ArrayList
*/
public ArrayList<Integer> spiralOrder (int[][] matrix) {
// write code here
if (matrix.length == 0)return new ArrayList<>();
int m = matrix.length;
int n = matrix[0].length;
int x = 0, y = 0; // 起始位置
int[] dx = new int[] {0, 1, 0, -1}; //行方向,右、下、左、上
int[] dy = new int[] {1, 0, -1, 0}; //列方向
int dir = 0; //起始方向
ArrayList<Integer> res = new ArrayList<>();
for (int i = 0; i < m * n; i++) {
res.add(matrix[x][y]);
matrix[x][y] = Integer.MAX_VALUE;
int nx = x + dx[dir];
int ny = y + dy[dir];
if (nx >= m || nx < 0 || ny >= n || ny < 0 ||
matrix[nx][ny] == Integer.MAX_VALUE) {
// 转向
dir = (dir + 1) % 4;
nx = x + dx[dir];
ny = y + dy[dir];
}
x = nx;
y = ny;
}
return res;
}
}
运行结果

三、顺时针旋转矩阵
有一个NxN整数矩阵,请编写一个算法,将矩阵顺时针旋转90度。
给定一个NxN的矩阵,和矩阵的阶数N,请返回旋转后的NxN矩阵。
数据范围:0<n<300,矩阵中的值满足 0≤val≤1000
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param mat int整型二维数组
* @param n int整型
* @return int整型二维数组
*/
public int[][] rotateMatrix (int[][] mat, int n) {
// write code here
/*** 核心思想:旋转 = 转置 + 每行反转
* - 转置:沿主对角线(左上→右下)交换元素
* - 行反转:将每一行的元素左右翻转 */
// 转置
for (int i = 0; i < n; i++) {
for (int j = 0; j < i; j++) {
int temp = mat[i][j];
mat[i][j] = mat[j][i];
mat[j][i] = temp;
}
}
// 行反转
for (int i = 0; i < n; i++) {
for (int j = 0; j < n / 2; j++) {
int temp = mat[i][j];
mat[i][j] = mat[i][n - 1 - j];
mat[i][n - 1 - j] = temp;
}
}
return mat;
}
}
运行结果

四、设计LRU缓存结构
设计LRU(最近最少使用)缓存结构,该结构在构造时确定大小,假设大小为 capacity ,操作次数是 n ,并有如下功能:
-
Solution(int capacity) 以正整数作为容量 capacity 初始化 LRU 缓存
-
get(key):如果关键字 key 存在于缓存中,则返回key对应的value值,否则返回 -1 。
-
set(key, value):将记录(key, value)插入该结构,如果关键字 key 已经存在,则变更其数据值 value,如果不存在,则向缓存中插入该组 key-value ,如果key-value的数量超过capacity,弹出最久未使用的key-value
提示:
1.某个key的set或get操作一旦发生,则认为这个key的记录成了最常使用的,然后都会刷新缓存。
2.当缓存的大小超过capacity时,移除最不经常使用的记录。
3.返回的value都以字符串形式表达,如果是set,则会输出"null"来表示(不需要用户返回,系统会自动输出),方便观察
4.函数set和get必须以O(1)的方式运行
5.为了方便区分缓存里key与value,下面说明的缓存里key用""号包裹
import java.util.*;
public class Solution {
//LRU缓存设计成hashmap+双向链表结构
Map<Integer, Node> cache = new HashMap<>(); //键为key,值是Node结点
Node left = new Node(0, 0); //lru
Node right = new Node(0, 0); //mr
int cap = 0; //容量
int len = 0; //结点个数
public Solution(int capacity) {
this.cap = capacity;
left.next = right;
right.prev = left;
}
public int get(int key) {
// 通过hashmap快速找到结点,移除节点,再将结点插入最末
if (cache.containsKey(key)) {
Node node = cache.get(key);
remove(node);
return insertTail(node);
}
return -1;
}
public void set(int key, int value) {
// 先判断是否存在,如果存在移除原节点,插入最末。
// 否则直接插入最末。cache put(key,val)。
// 判断len > cap,移除lru,及其hashmap lru.key
if (cache.containsKey(key)) {
remove(cache.get(key));
}
Node node = new Node(key, value);
insertTail(node);
cache.put(key, node);
if (len > cap) {
Node lru = left.next;
remove(lru);
cache.remove(lru.key);
}
}
public int insertTail(Node node) {
// 插入
Node prev = right.prev;
prev.next = node;
node.next = right;
right.prev = node;
node.prev = prev;
len++;
return node.val;
}
public int remove(Node node) {
//移除结点
Node prev = node.prev;
Node next = node.next;
prev.next = next;
next.prev = prev;
len--;
return node.val;
}
}
class Node {
int key;
int val;
Node prev;
Node next;
Node(int key, int val) {
this.key = key;
this.val = val;
}
Node(int key, int val, Node prev, Node next) {
this.key = key;
this.val = val;
this.prev = prev;
this.next = next;
}
}
运行结果

五、设计LFU缓存结构
一个缓存结构需要实现如下功能。
- set(key, value):将记录(key, value)插入该结构
- get(key):返回key对应的value值
但是缓存结构中最多放K条记录,如果新的第K+1条记录要加入,就需要根据策略删掉一条记录,然后才能把新记录加入。这个策略为:在缓存结构的K条记录中,哪一个key从进入缓存结构的时刻开始,被调用set或者get的次数最少,就删掉这个key的记录;
如果调用次数最少的key有多个,上次调用发生最早的key被删除
这就是LFU缓存替换算法。实现这个结构,K作为参数给出
import java.util.*;
public class Solution {
public int[] LFU(int[][] operators, int k) {
LFUCache lfu = new LFUCache(k);
List<Integer> res = new ArrayList<>();
for (int[] op : operators) {
if (op[0] == 1) {
lfu.put(op[1], op[2]);
} else {
res.add(lfu.get(op[1]));
}
}
return res.stream().mapToInt(Integer::intValue).toArray();
}
private static class LFUCache {
private final Map<Integer, Integer> keyToFreq = new HashMap<>();
private final Map<Integer, Map<Integer, Integer>> freqToMap = new HashMap<>();
private final int capacity;
private int minFreq;
public LFUCache(int capacity) {
this.capacity = capacity;
this.minFreq = 1;
}
public int get(int key) {
if (!keyToFreq.containsKey(key)) return -1;
return move(key, -1);
}
public void put(int key, int value) {
if (keyToFreq.containsKey(key)) {
move(key, value);
return;
}
if (keyToFreq.size() == capacity) {
Map<Integer, Integer> map = freqToMap.get(minFreq);
Integer removeKey = map.keySet().iterator().next();
map.remove(removeKey);
if (map.isEmpty()) freqToMap.remove(minFreq);
keyToFreq.remove(removeKey);
}
minFreq = 1;
if (!freqToMap.containsKey(minFreq)) freqToMap.put(minFreq,
new LinkedHashMap<>());
freqToMap.get(minFreq).put(key, value);
keyToFreq.put(key, minFreq);
}
private int move(int key, int value) {
Integer freq = keyToFreq.get(key);
Map<Integer, Integer> map = freqToMap.get(freq);
if (value == -1) value = map.get(key);
map.remove(key);
if (map.isEmpty()) {
freqToMap.remove(freq);
if (freq == minFreq) {
minFreq = freq + 1;
}
}
if (!freqToMap.containsKey(freq + 1)) freqToMap.put(freq + 1,
new LinkedHashMap<>());
freqToMap.get(freq + 1).put(key, value);
keyToFreq.put(key, freq + 1);
return value;
}
}
}
运行结果
