1.hashmap:最长不含重复字符的子字符串
class Solution {
public int lengthOfLongestSubstring(String s) {
if(s==null || s.length()==0){
return 0;
}
char[] c=s.toCharArray();
int start=0,maxLength=0;
HashMap<Character,Integer> memo=new HashMap<>();
for(int i=0;i<c.length;i++){
int tempLen=0;//临时长度记录,用于更新最大长度
//如果map中不包含该元素,则添加
if(!memo.containsKey(c[i])){
memo.put(c[i],i);
}else{
//否则就要一系列操作:
//(1)获取已存在元素的下标
//(2)更新start位置,目的是为了从重复元素的下一位置开始计算长度
int index=memo.get(c[i]);
//从重复元素的下一个位置开始计算长度,替换之前和原来的start位置进行比较
//取二者比较大的值,因为不能让start位置往回走,前面已经比较过了
start=Math.max(start,index+1);
memo.put(c[i],i);
}
tempLen=i-start+1;
maxLength=Math.max(maxLength,tempLen);
}
return maxLength;
}
}
2.动态规划:丑数
class Solution {
public int nthUglyNumber(int n) {
//动态规划
//每个丑数的获得=更小的丑数*因子(2,3,5)
int[] dp=new int[n];
dp[0]=1;
int a=0,b=0,c=0;//分别记录都哪些数乘过2,3,5了
for(int i=1;i<n;i++){
int n2=dp[a]*2,n3=dp[b]*3,n5=dp[c]*5;
dp[i]=Math.min(Math.min(n2,n3),n5);
if(dp[i]==n2){
a++;
}
if(dp[i]==n3){
b++;
}
if(dp[i]==n5){
c++;
}
}
return dp[n-1];
}
}
题解LeetCode
还是很懵。。。。不太懂
3.hashmap:第一个只出现一次的字符
class Solution {
public char firstUniqChar(String s) {
char[] c=s.toCharArray();
HashMap<Character,Integer> map=new HashMap<>();
for(char ch:c){
map.put(ch,map.getOrDefault(ch,0)+1);
}
for(int i=0;i<s.length();i++){
if(map.get(c[i])==1){
return c[i];
}
}
return ' ';
}
}
4.hashset:两个链表的第一个节点
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
Set<ListNode> set=new HashSet<>();
while(headA!=null){
set.add(headA);
headA=headA.next;
}
while(headB!=null){
if(!set.contains(headB)){
headB=headB.next;
}else{
return headB;
}
}
return null;
}
}
5.hashmap+二分法求边界:在排序数组中查找数字1
class Solution {
public int search(int[] nums, int target) {
//1.hash表
// HashMap<Integer,Integer> map=new HashMap<>();
// for(int i:nums){
// map.put(i,map.getOrDefault(i,0)+1);
// }
// return map.getOrDefault(target,0);
//2.二分法找到左右边界,左右边界的长度就是元素个数
if(nums.length==0) return 0;
int left=0,right=nums.length;
//找左边界
while(left<right){
int mid=left+(right-left)/2;
if(nums[mid]<target){
left=mid+1;
}else if(nums[mid]>target){
right=mid;
}else{
right=mid;
}
}
int left_bound=right;
//如果左边界不等于target,则证明没找到,这个数组里没有该元素
if(left_bound<nums.length && nums[left_bound]!=target){
return 0;
}
left=0;
right=nums.length;
//找右边界
while(left<right){
int mid=left+(right-left)/2;
if(nums[mid]<target){
left=mid+1;
}else if(nums[mid]>target){
right=mid;
}else{
left=mid+1;
}
}
int right_bound=right-1;
return right_bound-left_bound+1;
}
}