java每日练习-2019/06/09

代码有借鉴大神的写法,由于不清楚是哪位大神,所以在这里表示感谢~~~~

  1. 摆动排序II
  2. 坏了的计算器
  3. 删除造列II
  4. 移除掉k位数字
  5. 整数替换
  6. 重构字符串
    1. 给定一个无序的数组 nums,将它重新排列成 nums[0] < nums[1] > nums[2] < nums[3]… 的顺序。
    示例 1:
    输入: nums = [1, 5, 1, 1, 6, 4]
    输出: 一个可能的答案是 [1, 4, 1, 5, 1, 6]
    示例 2:
    输入: nums = [1, 3, 2, 2, 3, 1]
    输出: 一个可能的答案是 [2, 3, 1, 3, 1, 2]
    [1,5,1,1,6,4]
    [1,1,2,1,2,2,1]
public static void wiggleSort(int[] nums) {
		Arrays.sort(nums);
        int start=(nums.length+1)/2-1;
        int end=nums.length-1;
        int [] temp=new int[nums.length];
        int index=0;
        while(start>=0 && end>=(nums.length+1)/2) {
        	temp[index++]=nums[start--];
        	temp[index++]=nums[end--];
        }
        if(nums.length%2==1) {
        	temp[index]=nums[start];
        }
        //
     // System.out.println(Arrays.toString(temp));
       for(int i=0;i<nums.length;i++) {
    	   nums[i]=temp[i];
       }
    }

2. 在显示着数字的坏计算器上,我们可以执行以下两种操作:
双倍(Double):将显示屏上的数字乘 2;
递减(Decrement):将显示屏上的数字减 1 。
最初,计算器显示数字 X。
返回显示数字 Y 所需的最小操作数。
示例 1:
输入:X = 2, Y = 3
输出:2
解释:先进行双倍运算,然后再进行递减运算 {2 -> 4 -> 3}.
示例 2:
输入:X = 5, Y = 8
输出:2
解释:先递减,再双倍 {5 -> 4 -> 8}.
示例 3:
输入:X = 3, Y = 10
输出:3
解释:先双倍,然后递减,再双倍 {3 -> 6 -> 5 -> 10}.
示例 4:
输入:X = 1024, Y = 1
输出:1023
解释:执行递减运算 1023 次

public static int brokenCalc(int X, int Y) {
		int n=0;
		while(X<Y) {
			if(Y%2==0) {
				Y=Y/2;
				n++;
			}else {
				Y=(Y+1)/2;
				n+=2;
			}
		}
		return n+X-Y;
    }

3. 给定由 N 个小写字母字符串组成的数组 A,其中每个字符串长度相等。
选取一个删除索引序列,对于 A 中的每个字符串,删除对应每个索引处的字符。
比如,有 A = [“abcdef”, “uvwxyz”],删除索引序列 {0, 2, 3},删除后 A 为[“bef”, “vyz”]。
假设,我们选择了一组删除索引 D,那么在执行删除操作之后,最终得到的数组的元素是按 字典序(A[0] <= A[1] <= A[2] … <= A[A.length - 1])排列的,然后请你返回 D.length 的最小可能值。
示例 1:
输入:[“ca”,“bb”,“ac”]
输出:1
解释:
删除第一列后,A = [“a”, “b”, “c”]。
现在 A 中元素是按字典排列的 (即,A[0] <= A[1] <= A[2])。
我们至少需要进行 1 次删除,因为最初 A 不是按字典序排列的,所以答案是 1。
示例 2:
输入:[“xc”,“yb”,“za”]
输出:0
解释:
A 的列已经是按字典序排列了,所以我们不需要删除任何东西。
注意 A 的行不需要按字典序排列。
也就是说,A[0][0] <= A[0][1] <= … 不一定成立。
示例 3:

输入:[“zyx”,“wvu”,“tsr”]
输出:3
解释:
我们必须删掉每一列。

public static int minDeletionSize(String[] strs) {
		if (strs == null || strs.length < 2) {
            return 0;
        }
        int arrLen = strs.length;
        int strLen = strs[0].length();
        // 如果cuts[i] = true, 那么我们不需要再检查 strs[i][j] > strs[i+1][j]
        boolean[] cuts = new boolean[arrLen];
        int ans = 0;
        boolean delete;

        for (int j = 0; j < strLen; j++) {
            delete = false;
            for (int i = 0; i < arrLen - 1; i++) {
                if (!cuts[i] && strs[i].charAt(j) > strs[i + 1].charAt(j)) {
                    ans++;
                    delete = true;
                    break;
                }
            }
            if (!delete) {
                // 更新cuts
                for (int i = 0; i < arrLen - 1; i++) {
                    if (strs[i].charAt(j) < strs[i + 1].charAt(j)) {
                        cuts[i] = true;
                    }
                }
            }
        }
        return ans;
        
    }

4. 给定一个以字符串表示的非负整数 num,移除这个数中的 k 位数字,使得剩下的数字最小。
注意:
num 的长度小于 10002 且 ≥ k。
num 不会包含任何前导零。
示例 1 :
输入: num = “1432219”, k = 3
输出: “1219”
解释: 移除掉三个数字 4, 3, 和 2 形成一个新的最小的数字 1219。
示例 2 :
输入: num = “10200”, k = 1
输出: “200”
解释: 移掉首位的 1 剩下的数字为 200. 注意输出不能有任何前导零。
示例 3 :
输入: num = “10”, k = 2
输出: “0”
解释: 从原数字移除所有的数字,剩余为空就是0。

public static String removeKdigits(String num, int k) {
		if(num.length()==k) {
			return "0";
		}
		//思路,从左到右,找第一个比后面大的字符,删除,清零,k次扫描。
		StringBuffer sb=new StringBuffer();
		for(int i=0;i<num.length();i++) {
			sb.append(num.charAt(i));
		}
		
		if(num.length()>k) {
			
			for(int i=0;i<k;i++) {
				int index=0;
				for(int j=1;j<sb.length() && sb.charAt(j)>=sb.charAt(j-1);j++) {
						index=j;
					}
                sb.delete(index, index+1);
                 while (sb.length() > 1 && sb.charAt(0) == '0') sb.delete(0, 1);
			}
           //  while (sb.length() > 1 && sb.charAt(0) == '0') sb.delete(0, 1);
		}
		return sb.toString();
    }

5. 给定一个正整数 n,你可以做如下操作:

  1. 如果 n 是偶数,则用 n / 2替换 n。
  2. 如果 n 是奇数,则可以用 n + 1或n - 1替换 n。
    n 变为 1 所需的最小替换次数是多少?
    示例 1:
    输入:
    8
    输出:
    3
    解释:
    8 -> 4 -> 2 -> 1
    示例 2:
    输入:
    7
    输出:
    4
    解释:
    7 -> 8 -> 4 -> 2 -> 1

    7 -> 6 -> 3 -> 2 -> 1
//用位运算,最后一位是0直接右移,最后两位都是1,且该数不是3是,就选择+1,否则就选择-1,直到该数变成1,为防止越界,把n变成长整型 c代码
	public static int integerReplacement(int n) {
		int count=0;
		long temp=n;
		while(temp!=1) {
			if((temp&3)==3&&temp!=3) {
				temp++;
			}else if((temp&1)==1) {
				temp--;
			}else {
				temp=temp/2;
			}
			count++;
		}
		return count;
    }

6. 给定一个字符串S,检查是否能重新排布其中的字母,使得两相邻的字符不同。
若可行,输出任意可行的结果。若不可行,返回空字符串。
示例 1:
输入: S = “aab”
输出: “aba”
示例 2:
输入: S = “aaab”
输出: “”

 /**
* 更高效的算法,思路如下:
*  找出出现频率最高的char,然后要把他们分隔开, 隔一个slot插值
*  对于其他所有的剩余字符,也是隔一个插入,因为长度小于一半,所以肯定不会重复
*/
public static String reorganizeString(String s){
   if (s == null || s.length() == 0) {
       return "";
   }
   //词频统计
   int[] count = new int[26];
   for (char c : s.toCharArray()) {
       count[c - 'a']++;
   }
   //寻找最大频率的字母
   int maxCount = 0;
   char letter = 0;
   for (int i = 0; i < 26; i++) {
       if (maxCount < count[i]) {
           maxCount = count[i];
           letter = (char) ('a' + i);
       }
   }
   //如果最大频率大于一半+1,则无法完成任务
   if (maxCount > (1 + s.length()) / 2) {
       return "";
   }

   //结果集
   char[] res = new char[s.length()];
   //index 维护下一个应该插入的位置
   //隔空插入最大频率字母
   int index = insert(count, res, 0, letter);

   //插入其他字母
   for (int i = 0; i < 26; i++) {
       index = insert(count, res, index, (char)('a' + i));
   }
   return new String(res);
}

private static int insert(int[] count, char[] res, int index, char letter) {
   int i = letter - 'a';
   while (count[i] > 0) {
       //因为index大于res长度的情况是之前从0开始间隔2插入了频率最高的字符,
       // 所以这里应该是从0和2之间的间隔开始
       if (index >= res.length) {
           index = 1;
       }
       res[index] = letter;
       count[i]--;
       index += 2;
   }
   //返回下一个能插入的位置
   return index;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值