1. 关于旋转数组
旋转数组求最小值,最大值,以及任意值:
https://leetcode.windliang.cc/leetCode-33-Search-in-Rotated-Sorted-Array.html
2. 198 House Robber
求数组前n个数字相乘的最大值, 与第198题 House Robber解决方法类似;动态规划时需要记住两对状态(显著特点:原题为一维数组的搜索问题,但DP数组的构建实际上是二维数组);
3. 264 Ugly number
题意:求第n个丑数,丑数指该数字的因子只能是2,3,5的组合,1为例外.
思路:假设前n个丑数的数组为ugly[n],在这个数组中,肯定有这样三个数,c1,c2,c3,这三个数分别乘以2,3,5就会比ugly数组中的所有值都大,因此,下一个数为min(c1*2,c2*3,c3*5)。只要从开始就记住c1,c2,c3的位置,每次新加入数字后,就更新相应的c1,c2,c3的位置(例如上一个ugly为c1*2,则c1需要更新为c1=c1+1,更新不要想的太复杂);
class Solution {
public int nthUglyNumber(int n) {
int[] c = new int[3];
int[] ugly = new int[n];
ugly[0] = 1;
for(int i=1;i
4. 3 求最长无重复字符串
考虑简单的一种情形,假设字符串为"abacdb",我们使用start表示上一个不重复的位置(start初始值为0),解释如下图所示(s即为start)。
因此,这道题,理解第三幅图是重点,此时,s的更新需要考虑上一步的情况,即在本次找到的s和上一次的s之前取最大值即可。简单来说,s只能向右移动,不能回退。
将向前查找使用hashmap来完成,则代码如下:
class Solution {
public int lengthOfLongestSubstring(String s) {
Map map = new HashMap();
int start=0,maxlength=0;
for(int i=0;imaxlength?length:maxlength;
map.put(ch,i);
}
return maxlength;
}
}
5 leetcode 第19题 删除链表的倒数第n个节点
解法一: 使用两遍循环来解,第一遍求链表总长度,然后使用总长度计算出正向的位置,第二遍循环删除该点;
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
int length = 1;
ListNode temp = head;
while(temp.next!=null){
length++;
temp = temp.next;
}
int N = length-n;
temp = head;
for(int i=0;i
解法二:双指针解法。即使用两个指针,这两个指针之间相差n个节点,然后向后移动,当最前面的指针移动到末尾时,后面的指针即是倒数第n个节点。这是解决链表问题常用的解法,例如在判断链表是否有环时也使用快慢指针;注意,链表题中为了便于处理,经常增加一个头结点
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
//只有一个节点时,删除自己会有异常,因此在前面多加一个节点
ListNode headNode = new ListNode(9527);
headNode.next = head;
ListNode fast=headNode,slow =headNode;
int i=0;
while(fast.next!=null){
if(n<=0){
slow = slow.next;
}
fast = fast.next;
n--;
}
if(slow.next!=null)
slow.next = slow.next.next;
return headNode.next ;
}
}
4 24 两两交换链表节点;48旋转图像;
注意:交换节点时不要形成环;矩阵的转置操作(其实遍历的是上三角),矩阵的换行操作(其实遍历的是一半的列);
5 49 字符串分组
注意:考察hashmap时,经常需要进行聚合key,但有时key稍微有些差异(例如这道题,字母相同,顺序不同的,也算作相同的key),所以需要对key寻找一个映射函数来区分,或者对key进行简单的变形;
public List> groupAnagrams(String[] strs) {
Map> map = new HashMap();
for(String s: strs){
char[] ch = s.toCharArray();
Arrays.sort(ch);
String key = String.valueOf(ch);
if(!map.containsKey(key)) map.put(key,new LinkedList());
map.get(key).add(s); //注意这里的操作,新元素也要增添进去;
}
return new ArrayList(map.values());
}
50. Pow(x, n)
求x的n次方,使用正常的循环解法时间太长,使用递归来解;
对于递归类的问题,首先写其递归方程:
然后分析能不能使用动态规划,这道题明显不需要使用;
class Solution {
public double myPow(double x, int n) {
if(n==0) return 1;
int p = n>0?n:-n;
double out = help(x,p);
if(n<0) return 1/out;
else return out;
}
public double help(double x,int n){
if(n==0) return 1.0;
double d = help(x,n/2);
return d*d*pow0(x,n%2);
}
public double pow0(double x,int n){
if(n==0) return 1.0;
else return x;
}
}
51. 69 开方
思路:使用牛顿迭代法开平方;
- 求迭代方程;
- 定义cur,pre;
- 更新cur,pre;
- 当abs(cur-pre)>0.0001时,结束
class Solution {
public int mySqrt(int x) {
double pre=1,cur=1;
do{
pre = cur;
cur = pre/2.0+x/(2*pre);
}while(Math.abs(cur-pre)>0.1);
return (int)cur;
}
}
70 跳台阶
刚开始使用DFS来解,但n太大时会超时;
class Solution {
public int climbStairs(int n) {
return help(n,0);
}
//------n>44时会超时----------
public int help(int n,int sum){
if(sum==n){
return 1;
}
if(sum>n){
return 0;
}
int c1=0,c2=0;
return help(n,sum+1)+help(n,sum+2);
}
}
使用动态规划来做:
注意,看当前状态是由前那几个状态到达的,这很重要,比如树型结构
分清是状态汇聚(多变1),还是状态分裂(1变多),这两种情况对应的DP的顺序定义不一样
class Solution {
public int climbStairs(int n) {
if(n==1) return 1;
int[] dp = new int[n+1];
dp[0] = 0;
dp[1] = 1;
dp[2] = 2;
for(int i=3;i<=n;i++){
dp[i] = dp[i-1]+dp[i-2];
}
return dp[n];
}
}
数组长度的一半的数
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
用栈结构来模拟:两数字不同时从数组中去掉,最后剩下的就是该数字;
https://bestswifter.com/arrayoccurmorethanhalf/
用次数的方法:该数字出现次数大于其他数字出现的数字之和;
https://zhuanlan.zhihu.com/p/39538880
数据流中位数
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。
import java.util.*;
public class Solution {
PriorityQueue minHeap = new PriorityQueue();
PriorityQueue maxHeap = new PriorityQueue(11, new Comparator(){
public int compare(Integer o1,Integer o2){
return o2.compareTo(o1);
}
});
int count = 0;
public void Insert(Integer num) {
count++;
if(count%2==0){
if(!maxHeap.isEmpty()&&numminHeap.peek()){
minHeap.offer(num);
num = minHeap.poll();
}
maxHeap.offer(num);
}
}
public Double GetMedian() {
double result = 0;
if(count%2==0){
result = (minHeap.peek()+maxHeap.peek())/2.0;
}
else{
result = maxHeap.peek();
}
return result;
}
}