641. Missing Intervals: 点击打开链接
思路:两端点和一头一尾形成的区间+for循环扫描中间形成的区间
例如:{3,4,50,75},lower=0,upper=99,题目可以理解成在0-99的区间,挖去了3,4,50,95四个点,求剩下的区间
区间:lower->3-1
75+1->upper
中间{3,4,50,75}的扫描
注意:Integer.MAX_VALUE+1=Integer.MIN_VALUE
例如:输入[2147483647],0,2147483647,
因为2147483647是Integer.MAX_VALUE,而2147483647+1=-2147483648,是Integer.MIN_VALUE
因此会输出["0->2147483646","-2147483648->2147483647"]
而期望输出["0->2147483646"]
所以三种情况每一种都要加上if判断
public class Solution {
/**
* @param nums a sorted integer array
* @param lower an integer
* @param upper an integer
* @return a list of its missing ranges
*/
public List<String> findMissingRanges(int[] nums, int lower, int upper) {
List<String> result = new ArrayList<String>();
if(nums==null || nums.length==0){ //注意corner case
getRange(result,lower,upper);
return result;
}
if(nums[0]!=Integer.MIN_VALUE){
getRange(result,lower,nums[0]-1);
}
for(int i=1;i<nums.length;i++){
if(nums[i-1]!=Integer.MAX_VALUE && nums[i]!=Integer.MIN_VALUE){
getRange(result,nums[i-1]+1,nums[i]-1);
}
}
if(nums[nums.length-1]!=Integer.MAX_VALUE){
getRange(result,nums[nums.length-1]+1,upper);
}
return result;
}
private void getRange(List<String> result,int start,int end){
if(start>end){
return;
}else if(start==end){
result.add(""+start);
return;
}else{
result.add(""+start+"->"+end);
}
}
}
156. Merge Intervals: 点击打开链接
思路:区间start端点从小到大排序,从左到右扫一遍
能合并,就合并
不能合并,直接下一个
[ [ [1,
3
], [1, 6], [
2
, 6], => [8, 10], [8, 10], [15, 18] [15, 18] ] ]
分析:开始last=null,i=[1,3],res加入[1,3],并且last=[1,3];
i=[2,6],和last=[1,3]可以合并,更新res里[1,3]的end值使称为[1,6];
i=[8,10],res加入[8,10],并且last=[8,10];
注意:时间复杂度O(nlogn)
扫描一次n,排序nlogn
/**
* Definition of Interval:
* public class Interval {
* int start, end;
* Interval(int start, int end) {
* this.start = start;
* this.end = end;
* }
*/
class Solution {
/**
* @param intervals, a collection of intervals
* @return: A new sorted interval list.
*/
public List<Interval> merge(List<Interval> intervals) {
ArrayList<Interval> res = new ArrayList<>();
Collections.sort(intervals,myComparator);
Interval last=null;
for(Interval i:intervals) {
if(last==null || last.end<i.start){
res.add(i);
last=i;
} else{
last.end = Math.max(last.end, i.end); //更新已经在result list里的元素的end
}
}
return res;
}
private Comparator<Interval> myComparator = new Comparator<Interval>() {
public int compare(Interval i, Interval j) {
return i.start - j.start;
}
};
}
public int[][] merge(int[][] intervals) {
if(intervals == null || intervals.length <2)
{
return intervals;
}
Arrays.sort(intervals, (a,b) -> Integer.compare(a[0], b[0]));
List<int[]> list = new ArrayList<>();
for(int i=0; i<intervals.length; i++)
{
int left = intervals[i][0];
int right = intervals[i][1];
while(i+1<intervals.length && right >= intervals[i+1][0])
{
right = Math.max(right, intervals[i+1][1]);
i++;
}
list.add(new int[]{left, right});
}
return list.toArray(new int[list.size()][]);
}
30. Insert Intervals: 点击打开链接
Insert [2, 5] into [[1,2], [5,9]], we get [[1,9]].
Insert [3, 4] into [[1,2], [5,9]], we get [[1,2], [3,4], [5,9]]
/**
* Definition for an interval.
* public class Interval {
* int start;
* int end;
* Interval() { start = 0; end = 0; }
* Interval(int s, int e) { start = s; end = e; }
* }
*/
public class Solution {
public List<Interval> insert(List<Interval> intervals, Interval newInterval) { //方法一
List<Interval> result=new ArrayList<>();
int index=0;
while(index<intervals.size() && intervals.get(index).start<newInterval.start){ //先插入到正确位置
index++; //使整个给定list还是按start升序
}
intervals.add(index,newInterval);
Interval last=null; //然后是merge Intervals
for(Interval i:intervals){
if(last==null || last.end<i.start){
result.add(i);
last=i;
}else if(last.end>=i.start){
last.end=Math.max(i.end,last.end);
}
}
return result;
}
}
/**
* Definition of Interval:
* public classs Interval {
* int start, end;
* Interval(int start, int end) {
* this.start = start;
* this.end = end;
* }
*/
class Solution {
/**
* Insert newInterval into intervals.
* @param intervals: Sorted interval list.
* @param newInterval: A new interval.
* @return: A new sorted interval list.
*/
public ArrayList<Interval> insert(ArrayList<Interval> intervals, Interval newInterval) { //方法二
ArrayList<Interval> result = new ArrayList<Interval>();
for(Interval i: intervals){
if(i.end < newInterval.start){ //insert[3,4]与[1,2]比较
result.add(i);
}else if(i.start > newInterval.end){ //insert[3,4]与[5,9]比较
result.add(newInterval);
newInterval = i;
}else{ //其他情况就是start取小,end取大
int newStart = Math.min(i.start, newInterval.start);
int newEnd = Math.max(newInterval.end, i.end);
newInterval = new Interval(newStart, newEnd); //并且不断更新newInterval
}
}
result.add(newInterval);
return result;
}
}
646. First Position Unique Character:点击打开链接
public class Solution {
/**
* @param s a string
* @return it's index
*/
public int firstUniqChar(String s) {
if(s==null || s.length()==0){
return -1;
}
Map<Character,Integer> map=new HashMap<>();
for(int i=0;i<s.length();i++){
char ch=s.charAt(i);
if(!map.containsKey(ch)){
map.put(ch,1);
}else{
map.put(ch,map.get(ch)+1);
}
}
for(int i=0;i<s.length();i++){ //这里可以直接返回i
if(map.get(s.charAt(i))==1){
return i;
}
}
return -1;
}
}
423. Valid Parentheses:点击打开链接
思路:如果"([{}])",遇到前三个,stack里装了)]},当到了},stack该push},一样就继续遍历,不一样就返回false
public class Solution {
/**
* @param s A string
* @return whether the string is a valid parentheses
*/
public boolean isValidParentheses(String s) {
if(s==null || s.length()==0){
return false;
}
Stack<Character> stack=new Stack<>();
for(int i=0;i<s.length();i++){
char c=s.charAt(i);
if(c=='('){
stack.push(')');
}else if(c=='{'){
stack.push('}');
}else if(c=='['){
stack.push(']');
}else if(stack.isEmpty()||stack.pop()!=c){ //如果"()]",当遇到]stack该执行pop,但没有东西在stack里
return false; //还有就是如果pop出的不一样,也返回false
}
}
return stack.isEmpty(); //如果")()",如果一开始就该pop,stack此时为空,还是要返回false
}
}
647. Substring Anagrams:点击打开链接
思路:统计好p字符串每个字符出现的次数
sliding window从左往右扫一遍,每次判断p.length区间段的字符是不是能还原成p字符串
都是减少一个左边元素,同时增加一个右边元素,
public class Solution {
/**
* @param s a string
* @param p a non-empty string
* @return a list of index
*/
public List<Integer> findAnagrams(String s, String p) {
List<Integer> result=new ArrayList<>();
int[] temp=new int[26];
for(Character i:p.toCharArray()){
temp[i-'a']++;
}
int start=0,end=0;
int matched=0;
while(end<s.length()){
if(temp[s.charAt(end)-'a'] >=1){ //开始已经统计过p字符串,因此只要分p里有的,这里的个数至少为1
matched++; //每一个符合条件的都matched++
}
temp[s.charAt(end)-'a']--; //已经统计到matched上的,就要从自身字符的总个数上减掉
end++; //或者是不matched的,也要从自身字符的总个数上减掉,会成为-1或更小负数
if(matched==p.length()){ //没达到p.length不会添加
result.add(start);
}
if(end-start==p.length()){ //一开始从索引0往后遍历end,没达到p.length(),这里不执行
if(temp[s.charAt(start)-'a'] >=0){ //当达到p.length()才进行sliding window
matched--; //如果遍历到的字符自身总个数>=0,说明一开始end遍历的时候属于p里的字符
} //减少一个左边的字符
temp[s.charAt(start)-'a']++; //但是要补回来左边减少的字符,以便接下来end判断右面是不是有这个字符
start++; //如果左边这个字符不是p里有的,也要统计上,因为之前end遍历的时候已经成负数
} //因此怎么加也不是在下一次end判断的时候自身字符总数>=1
}
return result;
}
}
648. Word Abbreviation Set: 点击打开链接
方法一
思路:单词在字典中出现次数等于对应缩写在字典中的次数,unique
单词在字典中出现次数等于对应缩写在字典中的次数,not unique
public class ValidWordAbbr {
// @param dictionary a list of word
Map<String,Integer> mapA=new HashMap<>();
Map<String,Integer> mapW=new HashMap<>();
public ValidWordAbbr(String[] dictionary) {
for(String word:dictionary){
String abbr=getAbbr(word);
if(!mapA.containsKey(abbr)){
mapA.put(abbr,1);
}else{
mapA.put(abbr,mapA.get(abbr)+1);
}
}
for(String word:dictionary){
if(!mapW.containsKey(word)){
mapW.put(word,1);
}else{
mapW.put(word,mapW.get(word)+1);
}
}
}
/**
* @param word a string
* @return true if its abbreviation is unique or false
*/
public boolean isUnique(String word) {
return mapA.get(getAbbr(word))==mapW.get(word);
}
private String getAbbr(String word){
if(word.length()<=2){
return word;
}
return ""+word.charAt(0)+String.valueOf(word.length()-2)+word.charAt(word.length()-1);
}
}
/**
* Your ValidWordAbbr object will be instantiated and called as such:
* ValidWordAbbr obj = new ValidWordAbbr(dictionary);
* boolean param = obj.isUnique(word);
*/
方法二
思路:Map<缩写词,第一个遍历的单词>,当map里已经有这个缩写词,就要看下对应值的是不是同一个单词,如果不是,说明不是唯一
注意:在判断是不是唯一的时候,如果新的单词不是字典里已经有的,说明也是唯一
public class ValidWordAbbr {
// @param dictionary a list of word
Map<String,String> map;
public ValidWordAbbr(String[] dictionary) {
map=new HashMap<>();
for(String word:dictionary){
String abbr=getAbbr(word);
if(!map.containsKey(abbr)){
map.put(abbr,word);
}else{ //如果map里有key有abbr
if(!map.get(abbr).equals(word)){ //判断key对应的值映射不是当前word,而是之前已经有的word
map.put(abbr,"-1"); //说明不是唯一,用"-1"来记
}
}
}
}
/**
* @param word a string
* @return true if its abbreviation is unique or false
*/
public boolean isUnique(String word) {
String abbr=getAbbr(word); //返回true的两种情况
if(!map.containsKey(abbr)){ //给出word的abbr不在字典里
return true;
}
return map.get(abbr).equals(word)?true:false; //map的值映射是word,因为如果不是唯一值映射就是"-1"
}
private String getAbbr(String word){
if(word.length()<=2){
return word;
}
return ""+word.charAt(0)+String.valueOf(word.length()-2)+word.charAt(word.length()-1);
}
}
/**
* Your ValidWordAbbr object will be instantiated and called as such:
* ValidWordAbbr obj = new ValidWordAbbr(dictionary);
* boolean param = obj.isUnique(word);
*/
124. Longest Consecutive Sequence: 点击打开链接
例如:{100,4,200,1,3,2},对于数组里的每一个元素e,都看e-1和e+1是否在set里,如果在,就一直往下找,最后算出长度
为了能直接在set里判断,一开始就要把数组里所有元素放在set里
注意:因为只需要扫面一遍数组里的元素,因此O(n)
public class Solution {
/**
* @param nums: A list of integers
* @return an integer
*/
public int longestConsecutive(int[] num) {
if(num == null || num.length == 0){
return 0;
}
Set<Integer> set=new HashSet<>();
for(Integer e:num){
set.add(e);
}
int result=0;
for(Integer e:num){
int pre=e-1;
int next=e+1;
while(set.contains(pre)){
set.remove(pre);
pre--;
}
while(set.contains(next)){
set.remove(next);
next++;
}
result=Math.max(result,next-pre-1);
}
return result;
}
}
526. Load Balancer:点击打开链接
思路:O(1)时间内插入,删除,只能hash
但是还要getRandom(),就要数组或者list来做
public class LoadBalancer {
// This is consistent hashing solution in most companies. However it exceeds the memory limit
List<Integer> list;
Map<Integer,Integer> map;
public LoadBalancer() {
list=new ArrayList<>();
map=new HashMap<>();
}
// @param server_id add a new server to the cluster
// @return void
public void add(int server_id) {
list.add(server_id); //list加入这个元素,其实每次加入的元素都是在list末尾
map.put(server_id,list.size()-1); //map里放要添加的server_id和它在list里的位置
}
// @param server_id server_id remove a bad server from the cluster
// @return void
public void remove(int server_id) {
if(map.containsKey(server_id)){
int index=map.get(server_id); //拿到要删除的server_id在map里的位置
list.set(index,list.get(list.size()-1)); //list把该位置更新成最后一个元素
map.put(list.get(list.size()-1),index); //map里也把该位置更新成list的最后一个元素
list.remove(list.size()-1); //删除list最后一个元素
map.remove(server_id); //map删除要删除的server_id
}
}
// @return pick a server in the cluster randomly with equal probability
public int pick() {
Random r = new Random();
return list.get(r.nextInt(list.size())); //r.nextInt(n):表示从0到n(不包括n)随机取数
}
}