leetcode949
class Solution {
public String largestTimeFromDigits(int[] A) {
int[] f = new int[10];
for(int x : A)f[x]++;
for(int h = 23;h >= 0;h--){
for(int m = 59;m >= 0;m--){
int[] g = new int[10];
for(int i = h, j = 0;j < 2;i /= 10,j++)g[i%10]++;
for(int i = m, j = 0;j < 2;i /= 10,j++)g[i%10]++;
if(Arrays.equals(f, g))return String.format("%02d:%02d", h, m);//将h,m以两位的形式按字符串输出
}
}
return "";
}
}
leetcode332
HashMap<String, PriorityQueue<String>> map = new HashMap<String, PriorityQueue<String>>();
LinkedList<String> result = new LinkedList<String>();
public List<String> findItinerary(String[][] tickets) {
for (String[] ticket : tickets) {
if (!map.containsKey(ticket[0])) {
PriorityQueue<String> q = new PriorityQueue<String>();
map.put(ticket[0], q);
}
map.get(ticket[0]).offer(ticket[1]);
}
fun("JFK");
return result;
}
public void fun(String s) {
PriorityQueue<String> q = map.get(s);
while (q != null && !q.isEmpty()) {
fun(q.poll());
}
result.addFirst(s);
}
使用优先级队列,来保证每次取出的都是按英文字母排序最小的(同时对于有去无回的情况,必定是放在最后面,然后结果从最后加回来)
leetcode488
class Solution {
public int dfs(String board,int[]a1){
if(board.equals(""))return 0;
int len=board.length();
int res=Integer.MAX_VALUE;
for(int i=0;i<len;){
int j=i++;
while (i<len&&board.charAt(i)==board.charAt(j))i++;
int inc=3-i+j;
int used=inc>0?inc:0;
if(a1[board.charAt(j)-'A']-used>=0){
a1[board.charAt(j)-'A']-=used;
int temp=dfs(board.substring(0,j)+board.substring(i,len),a1);
if(temp>=0)res=Math.min(temp+used,res);
a1[board.charAt(j)-'A']+=used;
}
}
return res==Integer.MAX_VALUE?-1:res;
}
public int findMinStep(String board, String hand) {
int[]a1=new int[26];
for(char c:hand.toCharArray()){
a1[c-'A']++;
}
return dfs(board,a1);
}
}
利用string的不可变性和递归,进行字符串消除。
利用两个指针,自加,确定消除范围
利用递归返回值+used值,得到最后的返回值,即,每一次返回的都是最小,然后实现最后总的最小(有点dp的味道)
leetcode753
首先,对于数学上n位数,总是能取后n-1位然后加一位新的,构成一个新的数;这样做完以后,可以把k^n种情况全部遍历一遍。(具体原因未知,反正这样做就可以了)
这里比较漂亮的地方在于,利用stringbuilder的可变性,最终构造出答案,同时利用if(dfs())成功,直接返回,这一特性,使得在找到答案之后直接返回。利用hashset去重(这里所有的情况不是用boolean来判断,而是用hashset来判断)
class Solution {
public boolean dfs(StringBuilder res,int total,int n,int k,HashSet<String>a,int count){
if(count==total)return true;
String temp=res.substring(res.length()-n+1);
for(int i=0;i<k;i++){
if(a.contains(temp+(char)(i+'0')))continue;
res.append((char)(i+'0'));
a.add(temp+(char)(i+'0'));
if(dfs(res,total,n,k,a,count+1))return true;
a.remove(temp+(char)(i+'0'));
res.deleteCharAt(res.length()-1);
}
return false;
}
public String crackSafe(int n, int k) {
StringBuilder res=new StringBuilder();
for(int i=0;i<n;i++){
res.append('0');
}
HashSet<String>a=new HashSet<>();
a.add(res.toString());
int count=1;
dfs(res,(int)Math.pow(k,n),n,k,a,count);
return res.toString();
}
}
leetcode966
1.数组变hashset Arrays.asList(wordlist)
2.hashmap putifAbsent,只将第一个非重复的元素记录下来
public String[] spellchecker(String[] wordlist, String[] queries) {
Set<String> words = new HashSet<>(Arrays.asList(wordlist));
HashMap<String, String> cap = new HashMap<>();
HashMap<String, String> vowel = new HashMap<>();
for (String w : wordlist) {
String lower = w.toLowerCase(), devowel = lower.replaceAll("[aeiou]", "#");
cap.putIfAbsent(lower, w);
vowel.putIfAbsent(devowel, w);
}
for (int i = 0; i < queries.length; ++i) {
if (words.contains(queries[i])) continue;
String lower = queries[i].toLowerCase(), devowel = lower.replaceAll("[aeiou]", "#");
if (cap.containsKey(lower)) {
queries[i] = cap.get(lower);
} else if (vowel.containsKey(devowel)) {
queries[i] = vowel.get(devowel);
} else {
queries[i] = "";
}
}
return queries;
}
leetcode 691
首先,dp公式在于,dp[strnew]=min(dp[strnew-sticker]+1);
那么难点在于,如何利用字符串,作为dp的索引,所以这里用到了hashmap
但是对于不同的字符串,字母的排列方式也不一样,但各类字符的总数可能一样!因此,这里又出现了一个新的难点,如何解决字符总数一样但排列方式不一样!因此,这里采用的是将string变为charArray之后,再重新排列,aaabbb这样
那么如何解决在一个字符串中减去另一个字符串呢?方法是,首先记录总的,然后再对于每个字符串,数组记录个数,total-every,最后构建一个新的字符串。
还有一个难点,如何判断一个字符串中是否含有目标字符串中的任意一个字符呢?这里采用的方法是从开头开始判断,每次解决开头的字符(因为最终要解决所有的)。
class Solution {
public int minStickers(String[] stickers, String target) {
int len=stickers.length;
int[][]mp=new int[len][26];
for(int i=0;i<len;i++){
for(char c : stickers[i].toCharArray())mp[i][c-'a']++;
}
Map<String,Integer>dp=new HashMap<>();
dp.put("",0);
return help(mp,dp,target,len);
}
int help(int[][]mp,Map<String,Integer>dp,String target,int len){
if(dp.containsKey(target))return dp.get(target);
int[]tar=new int[26];
for(char c:target.toCharArray())tar[c-'a']++;
int res=Integer.MAX_VALUE;
for(int i=0;i<len;i++){
if(mp[i][target.charAt(0)-'a']==0)continue;
StringBuilder t=new StringBuilder();
for(int j=0;j<26;j++){
int l=Math.max(tar[j]-mp[i][j],0);
for(int k=0;k<l;k++)t.append((char)('a'+j));
}
int b=help(mp,dp,t.toString(),len);
if(b<0)return -1;
res=Math.min(res,b+1);
}
dp.put(target,res);
return res==Integer.MAX_VALUE?-1:res;
}
}
leetcode 43字符串相乘(同时也是拼多多笔试题,大整数相乘)
思路:第1个字符串的第i位乘以第2个字符串的第j位,结果可以储存在数组的第i+j位,最后,只需要将数组中的所有元素取出,然后相加即可。
几点需要注意:
1.首位为0的字符应当删除
2.取出之后当前位取模,其他位根据除法结果可能增加
3.删除的时候至少要保留1位,即"0"*"0"="0",这时候的0不应该删除
public String multiply(String num1, String num2) {
int[]num=new int[num1.length()+num2.length()+2];
char[]a1=num1.toCharArray(),a2=num2.toCharArray();
int len1=a1.length-1,len2=a2.length-1;
for(int i=len1;i>=0;i--){
int b=a1[i]-'0';
for(int j=len2;j>=0;j--){
num[len1-i+len2-j]+=(a2[j]-'0')*b;
}
}
StringBuilder res=new StringBuilder();
for(int i=0;i<num.length;i++){
int v=num[i];
num[i]=v%10;
v/=10;
int cur=i+1;
while (cur<num.length&&v>0){
num[cur++]+=v%10;
v/=10;
}
res.insert(0,(char)(num[i]+'0'));
}
while (res.length()>1&&res.charAt(0)=='0'){
res.deleteCharAt(0);
}
return res.toString();
}