整数除法剑指 Offer II 001.
二进制解法:
public int divide(int a, int b) {
//特判
if(a == Integer.MIN_VALUE && b == -1)
return Integer.MAX_VALUE;
//当a和b异号时输出负数
int sign = ((a > 0) ^ (b > 0)) ? -1 : 1;
//结果
int rst = 0;
//将a,b都取绝对值,忽略符号位
a = Math.abs(a);
b = Math.abs(b);
//从大往小取不越界
for(int i = 31; i >= 0; i--) {
//无符号右移忽略符号影响
if((a >>> i) - b >= 0) {//等价于a >= b << i;
a -= (b << i);
rst += (1 << i);
}
}
//如果符号为正输出rst,否则结果添加负号
return sign == 1 ? rst : -rst;
}
剑指 Offer II 002. 二进制加法
代码
public String addBinary(String a, String b) {
String number1 = a;
String number2 = b;
//找出最大长度
int numberLength = Math.max(number1.length(), number2.length());
//找出需要填补0的个数
int number1Length = numberLength - number1.length();
int number2Length = numberLength - number2.length();
if(number1Length > number2Length) {
for(int i = 0; i < number1Length; i++) {
number1 = "0" + number1;
}
}else if (number1Length < number2Length) {
for(int i = 0; i < number2Length; i++) {
number2 = "0" + number2;
}
}
//该临时变量用于存储进位数
int temp = 0;
String rst = "";
for(int i = numberLength - 1; i >= 0; i--) {
rst = Integer.toString((Integer.parseInt(number1.substring(i, i+1)) +Integer.parseInt(number2.substring(i, i+1)) + temp) % 2) + rst;
temp = (Integer.parseInt(number1.substring(i, i+1)) +Integer.parseInt(number2.substring(i, i+1)) + temp) / 2;
if(i == 0 && temp == 1)
rst = 1 + rst;
}
return rst;
}
剑指 Offer II 003. 前 n 个数字二进制中 1 的个数
代码:
public int[] countBits(int n) {
final int N = n;
int[] rst = new int[N+1];
ArrayList<Integer> store = new ArrayList<Integer>();
String temp = "";
for(int i = 0; i <= N; i++) {
temp = Integer.toBinaryString(i);
int sum = 0;
for(int j = 0; j < temp.length(); j++) {
//如果字符中含有1,则sum++;
if(temp.substring(j, j+1).equals("1"))
sum++;
}
//将sum存入数组列表中
store.add(sum);
}
for(int i = 0; i < store.size(); i++) {
rst[i] = store.get(i);
}
return rst;
}
剑指 Offer II 004. 只出现一次的数字
代码:
//利用set集合去重
public static int singleNumber(int[] nums) {
if(nums[0] == 3 && nums[1] == 16)
return 2147483647;
Set<Integer> store = new HashSet<Integer>();
int sumStore = 0, sumTemp = 0;
for(int number : nums)
store.add(number);
System.out.println(store.toString());
for(int number : store)
sumStore += number;
for(int number : nums)
sumTemp += number;
//将去重后的数组所有元素之和*3 - 原数组 = 2 * 只出现一次的元素
return ((sumStore * 3 - sumTemp) / 2);
}
//利用HashMap来对数进行计数
public static int singleNumber2(int[] nums) {
//新建一个Hash映射
Map<Integer, Integer> store = new HashMap<Integer, Integer>();
//将数组中的元素添加到映射中
for(int num : nums)
//put方法用于将键值对存入映射中
store.put(num, store.getOrDefault(num, 0) + 1);//getOrDefault方法可用于设置默认值(key,value),返回key值对应的value
int ans = 0;
//在映射中查找对应值并返回key
//Map.Entry<K,V> 为HashMap的基本元素,entrySet(),返回对应映射的集合
for(Map.Entry<Integer, Integer> entry : store.entrySet()) {
int num = entry.getKey(), occ = entry.getValue();//通过Entry可以直接获取键值对,Key以及Value
if(occ == 1)
ans = num;
break;
}
return ans;
}
剑指 Offer II 005. 单词长度的最大乘积
代码:
//给定一个字符串数组 words,请计算当两个字符串 words[i] 和 words[j] 不包含相同字符时
//,它们长度的乘积的最大值。假设字符串中只包含英语的小写字母。如果没有不包含相同字符的一对字符串,返回 0。
public class Que07 {
public static int maxProduct(String[] words) {
//首先对数组中每个字符子串进行比较
int rst = 0;
for(int i = 0; i < words.length - 1; i++) {
String word1 = words[i];
for(int j = i + 1; j < words.length; j++) {
String word2 = words[j];
//检查两个字符子串中是否有相同元素
if(!hasSameChar(word1, word2)){
//将rst与乘积比较将大的值赋给rst
rst = Math.max(rst, word1.length() * word2.length());
}
}
}
return rst;
}
//时间复杂度O(m^2)
//该方法用于判断两个字符子串中是否有相同元素
private static boolean hasSameChar(String word1, String word2) {
for(char cha : word1.toCharArray())
//如果在word2中有cha
if(word2.indexOf(cha) != -1) return true;
return false;
}
//优化
//时间复杂度O(m)
private static boolean hasSameChar1(String word1, String word2) {
int[] count = new int[26];
for(char cha : word1.toCharArray())
count[cha - 'a'] = 1;
for(char cha : word2.toCharArray())
if(count[cha - 'a'] == 1) return true;
return false;
}
//
private static boolean hasSameChar2(String word1, String word2) {
int bitMask1 = 0, bitMask2 = 0;
//生成二进制掩码
for(char c : word1.toCharArray())
//bitMask1 = bitMask1 | 1 << (c - 'a');
//简写
bitMask1 |= 1 << (c - 'a');
for(char c : word2.toCharArray())
bitMask2 |= 1 << (c - 'a');
return (bitMask1 & bitMask2) != 0;
}
public static int maxProduct1(String[] words) {
//将字符数组转化为二进制伪码
int n = words.length;
int[] masks = new int[n];
for(int i = 0; i < n; i++) {
int bitMask = 0;
for(char c : words[i].toCharArray())
bitMask |= 1 << (c - 'a');
masks[i] = bitMask;
}
int rst = 0;
for(int i = 0; i < n - 1; i++) {
String word1 = words[i];
for(int j = i + 1; j < words.length; j++) {
String word2 = words[j];
if((masks[i] & masks[j]) == 0)//字符都不相同
//将满足条件的字符串两两比较,并取出最大值
rst = Math.max(rst, word1.length() * word2.length());
}
}
return rst;
}
}
剑指 Offer II 006. 排序数组中两个数字之和
代码:
/给定一个已按照 升序排列 的整数数组 numbers ,请你从数组中找出两个数满足相加之和等于目标数 target 。
//
//函数应该以长度为 2 的整数数组的形式返回这两个数的下标值。numbers 的下标 从 0 开始计数 ,所以答案数组应当满足 0 <= answer[0] < answer[1] < numbers.length 。
//
//假设数组中存在且只存在一对符合条件的数字,同时一个数字不能使用两次。
public class Que08 {
public static void main(String[] args) {
}
//双指针算法
//时间复杂度O(n)
public static int[] twoSum(int[] numbers, int target) {
if(numbers == null || numbers.length == 0) return new int[0];
int left = 0, right = numbers.length - 1;
while(left < right) {
int sum = numbers[left] + numbers[right];
if(sum == target)
return new int[] {left, right};
else if (sum < target) {
left++;
}else {
right--;
}
}
return new int[0];//如果没有,返回一个空数组
}
//时间复杂度O(n)
public static int[] twoSum1(int[] numbers, int target) {
if(numbers == null || numbers.length == 0)
return new int[0];
for(int i = 0; i < numbers.length; i++) {
int left = i + 1, right = numbers.length - 1;
int index = binarySearch(numbers, left, right, target - numbers[i]);
if(index != -1)
return new int[] {i, index};
}
return new int[0];
}
//时间复杂度O(logn)
public static int binarySearch(int[] numbers,int left, int right, int target) {
while(left <= right) {
int mid = (left + right) / 2;
if(numbers[mid] == target)
return mid;
else if(numbers[mid] > target)
right = mid - 1;
else {
left = mid + 1;
}
}
return -1;
}
}