867. Transpose Matrix

867. Transpose Matrix

Question

Given a 2D integer array matrix, return the transpose of matrix.

The transpose of a matrix is the matrix flipped over its main diagonal, switching the matrix’s row and column indices.

Solution

记录一个新数组res[][]。

双重循环,交换下标将matrix[i][j]复制到res[j][i],最后返回。

Code

1
2
3
4
5
6
7
8
9
10
11
class Solution {
public int[][] transpose(int[][] matrix) {
int[][] res = new int[matrix[0].length][matrix.length];
for(int i = 0; i < matrix.length; i++){
for(int j = 0; j < matrix[0].length; j++){
res[j][i] = matrix[i][j];
}
}
return res;
}
}
1480. Running Sum of 1d Array

1480. Running Sum of 1d Array

Question

Given an array nums. We define a running sum of an array as runningSum[i] = sum(nums[0]…nums[i]).

Return the running sum of nums.

Solution

类似动态规划,遍历数组,并将当前位置的元素和上一个位置的元素进行加和。

Code

1
2
3
4
5
6
7
8
class Solution {
public int[] runningSum(int[] nums) {
for(int i = 1; i < nums.length; i++){
nums[i] += nums[i-1];
}
return nums;
}
}
1461. Check If a String Contains All Binary Codes

1461. Check If a String Contains All Binary Codes

Question

Given a binary string s and an integer k, return true if every binary code of length k is a substring of s. Otherwise, return false.

Solution

位运算+哈希表,用整数num记录二进制编码并加入哈希表中。
首先将字符串内的前k位二进制码转换为整数。并将其数值添加到哈希表内。

滑动窗口遍历,维持num为k长度内二进制码所对应的整数,并在遍历时将num加入哈希集合。
如果哈希集合的size达到k长度对应的可组合数,则返回true,否则返回false。

位运算与掩码

为了维护整数num,首先将其二进制编码向左移动一位。
然后与mask进行按位与运算,屏蔽掉多余的位数。

mask的值为k长度对应的可组合数-1。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
public boolean hasAllCodes(String s, int k) {
if(s.length() < k) return false; //字符串长度不足则返回false
char[] bin = s.toCharArray();
int n = s.length(), m = (int) Math.pow(2, k);
HashSet<Integer> set = new HashSet<>(); //哈希表记录访问过的数字

int num = Integer.parseInt(s.substring(0,k), 2); //字符串以二进制转换为整数
int mask = m-1; //掩码等于寻找长度-1
set.add(num);

for(int i = k; i < s.length(); i++){ //位运算,维护窗口内整数的值
num <<= 1; //位运算左移一位
num &= mask; //出界的位置被掩码遮盖
if(bin[i] == '1') num++;
set.add(num);
if(set.size() == m) return true; //如果哈希表长度等于2^k,则已经遍历了所有组合,返回true
}
return false;
}
}
29. Divide Two Integers

29. Divide Two Integers

Question

Given two integers dividend and divisor, divide two integers without using multiplication, division, and mod operator.

The integer division should truncate toward zero, which means losing its fractional part. For example, 8.345 would be truncated to 8, and -2.7335 would be truncated to -2.

Return *the quotient after dividing dividend by *divisor.

**Note: **Assume we are dealing with an environment that could only store integers within the 32-bit signed integer range: [−2<sup>31</sup>, 2<sup>31</sup><span> </span>− 1]. For this problem, if the quotient is strictly greater than 2<sup>31</sup><span> </span>- 1, then return 2<sup>31</sup><span> </span>- 1, and if the quotient is strictly less than -2<sup>31</sup>, then return -2<sup>31</sup>.

Solution

解题思路类似于快速幂

使用快速乘法来快速的获得商。

计算过程相当于:
60/8 = (60-32)/8 + 4 = (60-32-16)/8 + 2 + 4 = 1 + 2 + 4 = 7

需要注意的是由于只使用了整数(int)而不是长整数(long)储存数据,因此计算时需要处理各种溢出问题。

整数溢出

由于采用32位整数记录数字,负数要比正数的值范围大1。
因此当divisor为负数时,如果负数为整数最小值,则需要返回对应的整数最大值。

同时,为了在计算时防止整数溢出,因此将被除数与除数统一转为负数计算。(负数的数值比整数范围大)
当向下递归时,要保持dividend和divisor的正负性不变。

快速乘

只要被除数大于除数,则商至少为1。
循环,当被除数大于两倍的除数时,则商的结果可以直接翻倍。

否则将被除数减去当前的除数,然后向下递归新的被除数和除数。
最后返回快速乘中计算出的商加上向下递归返回的结果。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
public int divide(int dividend, int divisor) {
if(dividend == 0) return 0;
if(divisor == 1) return dividend;
if(divisor == -1) return dividend == Integer.MIN_VALUE ? Integer.MAX_VALUE : -dividend; //当dividend为最小整数时,其负数溢出,此时返回Integer.MAX_VALUE
int a = dividend, b = divisor;
int sign = a > 0 && b > 0 || a < 0 && b < 0 ? 1 : -1; //记录除数与被除数是否同号
if(dividend > 0) a = -a; //将除数与被除数转换为负数,因为负数能记录的数值比正数大1,防止溢出
if(divisor > 0) b = -b;
if(a > b) return 0; //被除数小于除数时返回0
int res = 1;
while(a <= b+b && b+b < 0){ //算法核心,快速乘法
b += b; //除数每次翻倍,直到大于被除数
res += res; //商的结果翻倍
}
res = sign == 1 ? res : -res; //根据是否同号记录商

divisor = dividend > 0 ? -divisor : divisor; //当原有被除数是正数时,要将除数取反
return res + divide(a-b, divisor);
}
}
318. Maximum Product of Word Lengths

318. Maximum Product of Word Lengths

Question

Given a string array words, return the maximum value of length(word[i]) * length(word[j]) where the two words do not share common letters. If no such two words exist, return 0.

Solution

正常的思路可能是用哈希表保存字符串中出现过的字符。此时表的大小是26也是一个常数。

我们可以采用位运算进行状态压缩,通过一个整数的二进制位保存二十六个字符的存在状态。

状态压缩

我们采用一个整数数组bin[]储存状态压缩后的整数。

遍历每个字符串,在字符串中遍历每一个字符。
初始化整数bit为0。在遍历字符时计算当前字符与字符’a’距离的差n,然后将1左移n位,填入(或运算)整数bit中。

比较

遍历words[]中的两个字符串,当bin[i]与bin[j]进行与运算结果为0时,则两个字符串没有共同字符。
此时更新二者长度乘积的最大值max。

最后返回max即可。

时间复杂度:O(L + n2)。L为所有字符的总长度。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution {
public int maxProduct(String[] words) {

int max = 0;
int bin[] = new int[words.length];

for(int i = 0; i < words.length; i++){
int bit = 0;
for(int j = 0; j < words[i].length(); j++){
bit |= (1 << (words[i].charAt(j) - 'a'));
}
bin[i] = bit;
}

for(int i = 0; i < words.length; i++){
for(int j = i+1; j < words.length; j++){
if((bin[i] & bin[j]) == 0) max = Math.max(max, words[i].length() * words[j].length());
}
}
return max;
}
}