Java实现LeetCode 题号:481 - 490

190 阅读5分钟

这是我参与11月更文挑战的第29天,活动详情查看:2021最后一次更文挑战

LeetCode习题集 有些题可能直接略过了,整理一下之前刷leetcode

481. 神奇字符串

神奇的字符串 S 只包含 '1' 和 '2',并遵守以下规则:

字符串 S 是神奇的,因为串联字符 '1' 和 '2' 的连续出现次数会生成字符串 S 本身。

字符串 S 的前几个元素如下:S = “1221121221221121122 ......”

如果我们将 S 中连续的 1 和 2 进行分组,它将变成:

1 22 11 2 1 22 1 22 11 2 11 22 ......

并且每个组中 '1' 或 '2' 的出现次数分别是:

1 2 2 1 1 2 1 2 2 1 2 2 ......

你可以看到上面的出现次数就是 S 本身。

给定一个整数 N 作为输入,返回神奇字符串 S 中前 N 个数字中的 '1' 的数目。

注意:N 不会超过 100,000。

示例:

输入:6 输出:3 解释:神奇字符串 S 的前 6 个元素是 “12211”,它包含三个 1,因此返回 3。

 这个字符串的规律
i = 0,s2 = “”,尾部添加一个'1',str更新为“1i = 1,s2 = “1”,尾部添加str[index] - '0' = 2个 ‘2’,s2 更新为 “122”,
i = 2,s2 = “122”,尾部添加str[index] - '0' = 2个 ‘1’,s2 更新为 “122 11”,
i = 3,s2 = “12211”,尾部添加str[index] - '0' = 1个 ‘2’,s2 更新为“12211 2i = 4,s2 = “122112”,尾部添加str[index] - '0' = 1个 ‘1’,s2 更新 “122112 1”,
i = 5,s2 = “1221121”,尾部添加str[index] - '0' = 2个 ‘2’,s2 更新为“1221121 22i = 6,s2 = “122112122”,尾部添加str[index] - '0' = 1个‘1’,s2 更新 “122112122 1”,
i = 7,s2 = “1221121221”,尾部添加str[index] - '0' = 2个‘2’,s2 更新为“1221121221 22”

找到规律后,就很简单了
class Solution {
    public int magicalString(int n) {
        List<Integer> s2=new ArrayList<Integer>();
			 s2.add(1);s2.add(-1);s2.add(-1); 
			 int key=1;
			 for (int i = 2; i < n; i++) {
				if(s2.get(i)==1)
					s2.add(key);
				if(s2.get(i)==-1){
					s2.add(key);
					s2.add(key);
				}
				key=-key;
			}
			  key = 0;
			 for (int i = 0;i<n;i++) {
				if(s2.get(i)==1)
					key++;
			}
			return key;
    }
}

482. 密钥格式化

给定一个密钥字符串S,只包含字母,数字以及 '-'(破折号)。N 个 '-' 将字符串分成了 N+1 组。给定一个数字 K,重新格式化字符串,除了第一个分组以外,每个分组要包含 K 个字符,第一个分组至少要包含 1 个字符。两个分组之间用 '-'(破折号)隔开,并且将所有的小写字母转换为大写字母。

给定非空字符串 S 和数字 K,按照上面描述的规则进行格式化。

示例 1:

输入:S = "5F3Z-2e-9-w", K = 4

输出:"5F3Z-2E9W"

解释:字符串 S 被分成了两个部分,每部分 4 个字符; 注意,两个额外的破折号需要删掉。 示例 2:

输入:S = "2-5g-3-J", K = 2

输出:"2-5G-3J"

解释:字符串 S 被分成了 3 个部分,按照前面的规则描述,第一部分的字符可以少于给定的数量,其余部分皆为 2 个字符。

提示:

S 的长度不超过 12,000,K 为正整数 S 只包含字母数字(a-z,A-Z,0-9)以及破折号'-' S 非空

小写转大写
    后面的要凑成K个字符,不够的继续向后找
    向后找的过程中的破折号都要删掉
class Solution {
    public String licenseKeyFormatting(String S, int K) {
    	
    	 char [] inp=S.toCharArray(); //i1
         int L=inp.length, LL=2*L;
         char [] cal=new char [LL]; //i2
         int i1=L-1,i2=2*L-1,counter=K;
         char c;
         
         while( i1>=0 )
         {
           c=inp[i1--];
           
           if( c!='-' )
           {
             if(counter==0)
             {
               cal[i2--]='-';
               counter=K;
             }
             
             if(c>='a')
               c-=32;
             
             cal[i2--]=c;
             counter--;
           }           
         }
         return new String (Arrays.copyOfRange(cal,i2+1,2*L));           
    }
}

485. 最大连续1的个数

给定一个二进制数组, 计算其中最大连续1的个数。

示例 1:

输入: [1,1,0,1,1,1] 输出: 3 解释: 开头的两位和最后的三位都是连续1,所以最大连续1的个数是 3. 注意:

输入的数组只包含 0 和1。 输入数组的长度是正整数,且不超过 10,000。

二进制数组中:除了 0 就是 1
    检测有多少个1可以变成
    检测有多少个0, 如果当前位置为0,就把当前位置的0减去上一个位置的0-1 就是这段里面都是1
    最后输出的时候,看最后一段是不是1的连续,如果是1的连续,就用总长度减去上一个0位置,返回max
class Solution {
      public int findMaxConsecutiveOnes(int[] nums) {
        int pre=-1;
        int rs=0;
        for(int i=0;i<nums.length;i++){
            if(nums[i]==0){
                rs=Math.max(rs,i-pre-1);
                pre=i;
            }
        }
        rs=Math.max(nums.length-pre-1,rs);
        return rs;
    }
}

486. 预测赢家

给定一个表示分数的非负整数数组。 玩家1从数组任意一端拿取一个分数,随后玩家2继续从剩余数组任意一端拿取分数,然后玩家1拿,……。每次一个玩家只能拿取一个分数,分数被拿取之后不再可取。直到没有剩余分数可取时游戏结束。最终获得分数总和最多的玩家获胜。

给定一个表示分数的数组,预测玩家1是否会成为赢家。你可以假设每个玩家的玩法都会使他的分数最大化。

示例 1:

输入: [1, 5, 2] 输出: False 解释: 一开始,玩家1可以从1和2中进行选择。 如果他选择2(或者1),那么玩家2可以从1(或者2)和5中进行选择。如果玩家2选择了5,那么玩家1则只剩下1(或者2)可选。 所以,玩家1的最终分数为 1 + 2 = 3,而玩家2为 5。 因此,玩家1永远不会成为赢家,返回 False。 示例 2:

输入: [1, 5, 233, 7] 输出: True 解释: 玩家1一开始选择1。然后玩家2必须从5和7中进行选择。无论玩家2选择了哪个,玩家1都可以选择233。 最终,玩家1(234分)比玩家2(12分)获得更多的分数,所以返回 True,表示玩家1可以成为赢家。 注意:

1 <= 给定的数组长度 <= 20. 数组里所有分数都为非负数且不会大于10000000。 如果最终两个玩家的分数相等,那么玩家1仍为赢家。

class Solution {
    public boolean PredictTheWinner(int[] nums) {
        int sum = 0;
        for(int n : nums)
            sum += n;
        int len = nums.length;
        int[][] dp = new int[len][len];
        for(int i = 0; i < len; i++)
            dp[i][i] = nums[i];
        for(int j = 1; j < len; j++)
            dp[j-1][j] = Math.max(dp[j-1][j-1], dp[j][j]);
            //后者肯定会选大的,然后我就在他选完的基础上选小的,然后加上那个值选大的
        for(int i = 2; i < len; i++)
            for(int row = 0; i + row < len; row++)
                dp[row][row+i]  = Math.max(nums[row] + Math.min(dp[row+1][i+row-1], dp[row+2][i+row]),
                        nums[i+row] + Math.min(dp[row][i+row-2], dp[row+1][i+row-1]));
        return dp[0][len-1] >= (sum - dp[0][len-1]);
    }
}

488. 祖玛游戏

回忆一下祖玛游戏。现在桌上有一串球,颜色有红色(R),黄色(Y),蓝色(B),绿色(G),还有白色(W)。 现在你手里也有几个球。

每一次,你可以从手里的球选一个,然后把这个球插入到一串球中的某个位置上(包括最左端,最右端)。接着,如果有出现三个或者三个以上颜色相同的球相连的话,就把它们移除掉。重复这一步骤直到桌上所有的球都被移除。

找到插入并可以移除掉桌上所有球所需的最少的球数。如果不能移除桌上所有的球,输出 -1 。

示例: 输入: "WRRBBW", "RB" 输出: -1 解释: WRRBBW -> WRR[R]BBW -> WBBW -> WBB[B]W -> WW (翻译者标注:手上球已经用完,桌上还剩两个球无法消除,返回-1)

输入: "WWRRBBWW", "WRBRW" 输出: 2 解释: WWRRBBWW -> WWRR[R]BBWW -> WWBBWW -> WWBB[B]WW -> WWWW -> empty

输入:"G", "GGGGG" 输出: 2 解释: G -> G[G] -> GG[G] -> empty

输入: "RBYYBBRRB", "YRBGB" 输出: 3 解释: RBYYBBRRB -> RBYY[Y]BBRRB -> RBBBRRB -> RRRB -> B -> B[B] -> BB[B] -> empty 标注:

你可以假设桌上一开始的球中,不会有三个及三个以上颜色相同且连着的球。 桌上的球不会超过20个,输入的数据中代表这些球的字符串的名字是 "board" 。 你手中的球不会超过5个,输入的数据中代表这些球的字符串的名字是 "hand"。 输入的两个字符串均为非空字符串,且只包含字符 'R','Y','B','G','W'。

class Solution {
 int DFS(String board,Map<Character,Integer> num){
	        if(board.length()==0) return 0;
	        int ans = 0x3f3f3f3f,l = board.length(),need,i,j;
	        for(i = 0;i < l;i = j){
	            j = i + 1;
	            while(j < l && board.charAt(j) == board.charAt(i)) j++;
	            need = 3 - (j - i);//当前位置要满足三个球消除需要几个额外的。
	            if(need <= num.get(board.charAt(i))){
	                need = Math.max(0,need);//可能存在有连续消除的情况。此时need为负数。例如WWWW
	                 num.put(board.charAt(i),num.get(board.charAt(i))-need);
	                
	                String subStr = board.substring(0,i) + board.substring(j);
	                int cnt = DFS(subStr,num);
	                if(cnt >= 0)
	                    ans = Math.min(ans , need + cnt);
	                num.put(board.charAt(i), num.get(board.charAt(i))+need);
	               
	            }
	        }
	        if(ans == 0x3f3f3f3f) return -1;
	        else return ans;    
	    }
	    int findMinStep(String board, String hand) {
	        Map <Character,Integer> num = new HashMap<Character,Integer>();//这里要定义char
	        num.put('R', 0);
	        num.put('Y', 0);
	        num.put('B', 0);
	        num.put('G', 0);
	        num.put('W', 0);
	        
	        int l = hand.length();
	        for(int i = 0;i < l;i++){
	            num.put(hand.charAt(i), num.get(hand.charAt(i))+1);
	        }
	        return DFS(board,num);
	    }
}