leetcode刷题记录(342、509、482、796)

2019.1.18 leetcode 刷题总结

题号:342

给定一个整数 (32 位有符号整数),请编写一个函数来判断它是否是 4 的幂次方。

示例 1:
输入: 16
输出: true
示例 2:
输入: 5
输出: false

我的想法:

  1. 一个数若是4的幂,一定是2的幂,且幂次是偶数
  2. 幂次是偶数在二进制的体现就是,二进制数的长度是奇数,且出除最高位为1外,其余全为0

对应程序:

// java
class Solution {
    public boolean isPowerOfFour(int num) {
        if(num == 0) {
            return false;
        }
        
    	int length = Integer.toBinaryString(num).length();
    	if((num & (num-1)) != 0 || length % 2 == 0) {
    		return false;
    	}
    	
    	return true;
    }
}

题号:509

斐波那契数,通常用 F(n) 表示,形成的序列称为斐波那契数列。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是:
F(0) = 0, F(1) = 1
F(N) = F(N - 1) + F(N - 2), 其中 N > 1.
给定 N,计算 F(N)。

示例 1:
输入:2
输出:1
解释:F(2) = F(1) + F(0) = 1 + 0 = 1.
示例 2:
输入:3
输出:2
解释:F(3) = F(2) + F(1) = 1 + 1 = 2.

我的想法:

  1. 递归求解

对应程序:

// java
class Solution {
    public int fib(int N) {
        if(N == 0) {
            return 0;
        }else if(N == 1) {
    		return 1;
    	}else {
    		return fib(N - 1) + fib(N - 2);
    	}
    }
}

优化:

  1. 在递归算法中存在着重复计算:例如在计算F(4)时,F(2)就被重复计算了2次;计算F(5)时,F(2)被重复计算3次,F(3)被重复计算了2次。随着N的增大,重复计算会越来越多,因此比较耗时
  2. 用迭代法
程序:
// java
class Solution {
    public int fib(int N) {
        
		if(N == 0) {
			return 0;
		}
		
		if(N == 1) {
			return 1;
		}
		
		int topTwo = 0;
		int topOne = 1;
		int res = 0;
		
		for(int i = 2; i <= N; ++i) {
			res = topOne + topTwo;
			topTwo = topOne;
			topOne = res;
		}
		
		return res;
    }
}

速度要快非常多

题号: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 个字符。

我的想法:

  1. 题目不要理解错,我开始的时候就理解错了:题目说的 “除了第一个分组以外,每个分组要包含 K 个字符”的意思是,第一个组中的元素个数要小于等于K,以保证后面每个分组都是K个字符
  2. 将源字符串中的所有“-”去掉,所有字母转大写,根据K重新分组,每组中间拼接“-”
  3. 在循环体中拼接字符串要使用StringBuilder,不要使用“+”进行拼解,因为会产生大量的垃圾对象

对应程序:

// java
class Solution {
    public String licenseKeyFormatting(String S, int K) {
    	String str = S.replaceAll("-", "").toUpperCase();
    	int length = str.length();
        if(length == 0) {
            return "";
        }
        // 计算得到第一组有多少个字符
    	int firstGroupNum = length % K == 0?K:length % K;
    	
    	StringBuilder res = new StringBuilder(str.substring(0, firstGroupNum));
    	for(int i = firstGroupNum; i < str.length(); ++i) {
    		if((i - firstGroupNum) % K == 0) {
                // 每组中间拼解"-"
    			res.append("-");
    		}
    		
    		res.append(str.charAt(i));
    	}
    	
    	return res.toString();
    }
}

题号:796

给定两个字符串, A 和 B。
A 的旋转操作就是将 A 最左边的字符移动到最右边。 例如, 若 A = ‘abcde’,在移动一次之后结果就是’bcdea’ 。如果在若干次旋转操作之后,A 能变成B,那么返回True。

示例 1:
输入: A = ‘abcde’, B = ‘cdeab’
输出: true
示例 2:
输入: A = ‘abcde’, B = ‘abced’
输出: false

我的想法:

  1. 找出A中所有B的首个字符的位置索引,若不存在,返回false;
  2. 以找到的位置索引断开字符串A,重新拼接:将索引前面的字符串拼接到索引后面的字符串,比较新字符串和B是否相同,若相同,返回true;若不同,去操作下一个索引

对应程序:

// java
class Solution {
    public boolean rotateString(String A, String B) {
    	if(A.length() != B.length()) {
    		return false;
    	}
    	
    	if(A.equals(B)) {
    		return true;
    	}
    	char bFirstChar = B.charAt(0);
    	int upIndex = A.indexOf(bFirstChar, 0);
    	
    	if(upIndex == -1) {
    		return false;
    	}
    	
    	while(upIndex != -1) {
    		String str1 = A.substring(0, upIndex);
    		String str2 = A.substring(upIndex);
    		String tempStr = str2 + str1;
    		
    		if(B.equals(tempStr)) {
    			return true;
    		}else {
    			upIndex = A.indexOf(bFirstChar, upIndex+1);
    		}
    	}
    	
		return false;
    }
}

看到提交结果中有人直接将两个字符串A拼接,判断新的字符串中是否含有B。这种想法还是很厉害的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值