1、根据身高重建队列
/**
* 解题思路:先排序再插入
* 1.排序规则:按照先H高度降序,K个数升序排序
* 2.遍历排序后的数组,根据K插入到K的位置上
*
* 核心思想:高个子先站好位,矮个子插入到K位置上,前面肯定有K个高个子,矮个子再插到前面也满足K的要求
*
* @param people
* @return
*/
public int[][] reconstructQueue(int[][] people) {
// [7,0], [7,1], [6,1], [5,0], [5,2], [4,4]
// 再一个一个插入。
// [7,0]
// [7,0], [7,1]
// [7,0], [6,1], [7,1]
// [5,0], [7,0], [6,1], [7,1]
// [5,0], [7,0], [5,2], [6,1], [7,1]
// [5,0], [7,0], [5,2], [6,1], [4,4], [7,1]
Arrays.sort(people, (o1, o2) -> o1[0] == o2[0] ? o1[1] - o2[1] : o2[0] - o1[0]);
LinkedList<int[]> list = new LinkedList<>();
for (int[] i : people) {
list.add(i[1], i);
}
return list.toArray(new int[list.size()][2]);
}
2、和为s的连续正数序列
public int[][] findContinuousSequence(int target) {
int i = 1; // 滑动窗口的左边界
int j = 1; // 滑动窗口的右边界
int sum = 0; // 滑动窗口中数字的和
List<int[]> res = new ArrayList<>();
while (i <= target / 2) {
if (sum < target) {
// 右边界向右移动
sum += j;
j++;
} else if (sum > target) {
// 左边界向右移动
sum -= i;
i++;
} else {
// 记录结果
int[] arr = new int[j-i];
for (int k = i; k < j; k++) {
arr[k-i] = k;
}
res.add(arr);
// 左边界向右移动
sum -= i;
i++;
}
}
return res.toArray(new int[res.size()][]);
}
3、滑动窗口的最大值
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
if (nums == null || k < 1 || nums.length < k) {
return new int[0];
}
int index = 0;
int[] res = new int[nums.length - k + 1];
LinkedList<Integer> queue = new LinkedList<>();
for (int i = 0; i < nums.length; i++) {
// 在队列不为空的情况下,如果队列尾部的元素要比当前的元素小,或等于当前的元素
// 那么为了维持从大到小的原则,我必须让尾部元素弹出
while (!queue.isEmpty() && nums[queue.peekLast()] <= nums[i]) {
queue.pollLast();
}
// 不走 while 的话,说明我们正常在队列尾部添加元素
queue.addLast(i);
// 如果滑动窗口已经略过了队列中头部的元素,则将头部元素弹出
if (queue.peekFirst() == (i - k)) {
queue.pollFirst();
}
// 看看窗口有没有形成,只有形成了大小为 k 的窗口,我才能收集窗口内的最大值
if (i >= (k - 1)) {
res[index++] = nums[queue.peekFirst()];
}
}
return res;
}
}
4、n个骰子的点数
解题思路:
class Solution {
public double[] twoSum(int n) {
double[] pre={
1/6d,1/6d,1/6d,1/6d,1/6d,1/6d};
for(int i=2;i<=n;i++){
double[] tem=new double[5*i+1];
for(int m=0;m<pre.length;m++){
for(int k=0;k<6;k++){
tem[m+k]+=pre[m]/6;
}
}
pre=tem;
}
return pre;
}
}
5、圆圈中最后剩下的数字
class Solution {
public int lastRemaining(int n, int m) {
if(n==1){
return 0;
}
int tem=lastRemaining(n-1,m);
return (tem+m)%n;
}
}
6、股票问题
7、回文链表
方法一:两次遍历,第一次使用栈来存储节点,第二次进行比较。
class Solution {
//两次遍历,第一次使用栈来存储节点值,第二次比较值
public boolean isPalindrome(ListNode head) {
if(head==null||head.next==null){
return true;
}
ListNode tem=head;
Stack<Integer> stack=new Stack<>();
while(tem!=null){
stack.add(tem.val);
tem=tem.next;
}
tem=head;
while(tem!=null){
if(tem.val!=stack.pop()){
return false;
}
tem=tem.next;
}
return true;
}
}
第二种方法:快指针走到末尾,慢指针刚好到中间。其中慢指针将前半部分反转。
class Solution {
//快指针走到末尾,慢指针刚好到中间。其中慢指针将前半部分反转。
public boolean isPalindrome(ListNode head) {
if(head==null||head.next==null){
return true;
}
ListNode fast=head;
ListNode low=head;
ListNode pre=null;
ListNode now=head;
while(fast!=null&&fast.next!=null){
low=low.next;
fast=fast.next.next;
now.next=pre;
pre=now;
now=low;
}
if(fast!=null){
low=low.next;
}
while(low!=null){
if(pre.val!=low.val){
return false;
}
pre=pre.next;
low=low.next;
}
return true;
}
}
8、最长回文子串
class Solution {
//解题思路:中心扩散法
//遍历s中的每一个字符,例如此时索引为i,left=i-1,right=i+1
//若left的字符与i相等,则长度+1,left++,直到left没有与i相等的字符
//若right的字符与i相等,则长度+1,right++,直到right没有与i相等的字符
//left和right分别向两侧同时扩大,若left和right的字符相等,lrft--,right++
public String longestPalindrome(String s) {
if(s.length()<=1){
return s;
}
int left=0;
int right=0;
int max=0;
int[] arr=new int[2