快手面试题
题目描述
博主的思路: 先用一个集合list,存储0的下标,然后依次判断,这些0所在的位置能否种花,若能,则将flowerbed对应位置改为1;
具体代码:
class Solution {
public boolean canPlaceFlowers(int[] flowerbed, int n) {
if(n==0){
return true;
}
if(flowerbed.length==1&&flowerbed[0]==0&&n==1){
return true;
}
if(flowerbed.length==1&&flowerbed[0]==0&&n>1){
return false;
}
if(flowerbed.length==1&&flowerbed[0]==1&&n>=1){
return false;
}
List<Integer> list=new ArrayList<Integer>();
int count=0;
for(int i=0;i<flowerbed.length;i++){
if(flowerbed[i]==0){
list.add(i);
}
}
if(list.get(0)==0&&flowerbed[list.get(0)+1]==0){
flowerbed[0]=1;
count++;
}
for(int i=1;i<list.size();i++){
if(flowerbed[list.get(i)-1]==0&&list.get(i)!=flowerbed.length-1&&flowerbed[list.get(i)+1]==0){
flowerbed[list.get(i)]=1;
count++;
}else if(list.get(i)==flowerbed.length-1&&flowerbed[list.get(i)-1]==0){
flowerbed[list.get(i)]=1;
count++;
}
}
return count>=n; }
}
前面的代码写的不太美观,修正下
class Solution {
public boolean canPlaceFlowers(int[] flowerbed, int n) {
/*
分析题意:判断每个位置能否种花,要看他的前置结点和后置结点是否为0,有的话此节点可以种花
存在两个特殊的情况,如果是第一个位置的话,则只需要判断后置结点是否为0即可,
如果是最后一个位置,只需要判断前置结点是否为0即可,但是我们为了保证判断条件的一致性,
所以第一个花盆,让他的前置结点直接给0.最后一个花盆,后置结点直接给0
*/
int size=flowerbed.length;
for (int i=0;i<size;i++){
if (flowerbed[i]==1){
continue;
}
//如果当前位置为0 则判断其前置结点和后置结点是否为0
int pre=i==0?0:flowerbed[i-1];
int next=i==(size-1)?0:flowerbed[i+1];
if (pre==0&&next==0){
flowerbed[i]=1;
n--;
}
}
return n<=0;}
}
628. 三个数的最大乘积
题目描述:
思路:
通过归纳不难分析出,数组有五种情况
第一种:全正 最大为后三个相乘
第二种:全负 最大为后三个相乘
第三种:一个正 最大为前两个和最后一个相乘
第四种:两个正 最大为后三个或者前两个和最后一个相乘
第五种:三个正及以上 最大为后三个相乘或者前两个和最后一个相乘
总结发现,一个数组三个数的最大乘积,要么是数组的后三个乘积之和,要么是前两个和最后一个相乘。
方法一具体代码
class Solution {
public int maximumProduct(int[] nums) {
Arrays.sort(nums);
int n=nums.length;
return Math.max(nums[0]*nums[1]*nums[n-1],nums[n-1]*nums[n-2]*nums[n-3]);
}
}
方法二
线性扫描
在方法一中,我们实际上只要求出数组中最大的三个数以及最小的两个数,因此我们可以不用排序,用线性扫描直接得出这五个数。
具体代码
class Solution {
public int maximumProduct(int[] nums) {
// 最小的和第二小的
int min1 = Integer.MAX_VALUE, min2 = Integer.MAX_VALUE;
// 最大的、第二大的和第三大的
int max1 = Integer.MIN_VALUE, max2 = Integer.MIN_VALUE, max3 = Integer.MIN_VALUE;
for (int x : nums) {
if (x < min1) {
min2 = min1;
min1 = x;
} else if (x < min2) {
min2 = x;
}
if (x > max1) {
max3 = max2;
max2 = max1;
max1 = x;
} else if (x > max2) {
max3 = max2;
max2 = x;
} else if (x > max3) {
max3 = x;
}
}
return Math.max(min1 * min2 * max1, max1 * max2 * max3);
}
}
字节面试题
剑指 Offer 35. 复杂链表的复制
题目描述
方法一:哈希表+迭代
具体代码
class Solution {
public Node copyRandomList(Node head) {
if(head == null) return null;
Node cur = head;
Map<Node, Node> map = new HashMap<>();
// 3. 复制各节点,并建立 “原节点 -> 新节点” 的 Map 映射
while(cur != null) {
map.put(cur, new Node(cur.val));
cur = cur.next;
}
cur = head;
// 4. 构建新链表的 next 和 random 指向
while(cur != null) {
map.get(cur).next = map.get(cur.next);
map.get(cur).random = map.get(cur.random);
cur = cur.next;
}
// 5. 返回新链表的头节点
return map.get(head);
}
}
方法二:哈希表+回溯
具体代码
class Solution {
Map<Node, Node> cachedNode = new HashMap<Node, Node>();
public Node copyRandomList(Node head) {
if (head == null) {
return null;
}
if (!cachedNode.containsKey(head)) {
Node headNew = new Node(head.val);
cachedNode.put(head, headNew);
headNew.next = copyRandomList(head.next);
headNew.random = copyRandomList(head.random);
}
return cachedNode.get(head);
}
}