好久没有打周赛了,今天在紧张的考前复(预)习中抽时间打一场就很刺激。
总体来说这套题还算可以,难度适中。
题目大意就是给定一个数组,检测其中是否存在三个连续的奇数。
这个算是签到题啦,扫一遍记录一下就好:
class Solution {
public boolean threeConsecutiveOdds(int[] arr) {
int flag = 0;
int n = arr.length;
for(int i = 0;i < n;i++) {
if(arr[i] % 2 == 1) {
flag++;
}else {
flag = 0;
}
if(flag == 3) {
return true;
}
}
return false;
}
}
题目大意是给定一个数组,每次可以选择一对元素,给其中一个加一,另一个减一。问操作多少次后数组中元素都相同。
这道题也不难,注意到每次是给一个加一另一个减一,数组总和不变。最后结果一定是平均值。
如果数组是随机给定的,那么扫一遍统计每个元素到平均值差的绝对值,最后将加和除以2就是答案。
这个题目中数组中的元素存在规律。
即
a i = 2 i − 1 ( 1 ≤ i ≤ n ) a_i = 2i - 1 \\ (1 ≤i≤n) ai=2i−1(1≤i≤n)
也就是说,这个序列为:
1 , 3 , 5 , 7.... 1,3,5,7.... 1,3,5,7....
那这就好整了。可以按照元素个数,分奇偶进行讨论
a v g = a ⌊ n 2 ⌋ = n a n s = ∑ i = 1 ⌊ n 2 ⌋ ( a v g − a i ) = ∑ i = 1 ⌊ n 2 ⌋ ( n − 2 i + 1 ) avg = a_{\left \lfloor \frac{n} {2}\right \rfloor } = n\\ ans = \sum^ {\left \lfloor \frac{n} {2}\right \rfloor} _ {i = 1} (avg - a_i)\\ \ =\sum^ {\left \lfloor \frac{n} {2}\right \rfloor} _ {i = 1} (n - 2i+1) avg=a⌊2n⌋=nans=i=1∑⌊2n⌋(avg−ai) =i=1∑⌊2n⌋(n−2i+1)
利用等差数列求和公式,有:
a n s = ( ⌊ n 2 ⌋ + 1 ) ∗ ⌊ n 2 ⌋ ans = (\left \lfloor \frac{n} {2}\right \rfloor+ 1) *\left \lfloor \frac{n} {2}\right \rfloor ans=(⌊2n⌋+1)∗⌊2n⌋
a v g = a n 2 + a n 2 + 1 2 = n − 2 a n s = ∑ i = 1 n 2 ( a v g − a i ) = ∑ i = 1 n 2 ( n − 2 i − 1 ) avg = \frac{a_{\frac{n} {2}} + a_{\frac{n} {2} + 1}} {2} = n - 2\\ ans= \sum^ {\frac{n} {2}} _ {i = 1} (avg - a_i)\\ \ =\sum^ {\frac{n} {2} }_ {i = 1} (n - 2i-1) avg=2a2n+a2n+1=n−2ans=i=1∑2n(avg−ai) =i=1∑2n(n−2i−1)
利用等差数列求和公式,有:
a n s = n 2 ∗ n 2 ans = \frac{n} {2} * \frac{n} {2}\\ ans=2n∗2n
a n s = n 2 4 ans = \frac{n^2} {4} ans=4n2
public class Solution2 {
int minOperations(int n) {
if(n % 2 == 1) {
return (1 + n / 2) * (n / 2);
}else {
return n * n / 4;
}
}
}
题目大意是给定n个篮子和m个小球(n >=m),每个篮子都有一个一维坐标,两个小球的磁力值为|pi - pj|,p为小球所在篮子的位置。问最小磁力值最大是多少?
这个题,上来看到求最小值最大,那大概率跑不掉二分答案。
我们可以直接二分这个最小磁力值,然后每次遍历放置,检测是否能够放得下。
在二分之前,记得给所有篮子排个序
复杂度:
O ( n l o g ( m a x ( p i ) ) ) O(nlog(max(p_i))) O(nlog(max(pi)))
class Solution {
private boolean check(int k,int[] p,int m) {
int n = p.length;
int flag = p[0];
m--;
for(int i = 1;i < n;i++) {
if(p[i] - flag >= k) {
m--;
flag = p[i];
}
if(m == 0) {
return true;
}
}
return false;
}
public int maxDistance(int[] position, int m) {
Arrays.sort(position);
int n = position.length;
int l = 0,r = position[n - 1];
while(l < r) {
int mid = (l + r) / 2 + 1;
if(check(mid,position,m)) {
l = mid;
}else {
r = mid - 1;
}
}
return l;
}
}
题目大意是,给定n个橘子,每天可以选择三种吃法中的一种:
问最少多少天可以将橘子吃完
将题目翻译一下,可以得到:
给定一个数字n,每次选择三种操作中的一种:
问最少多少次操作可以将数字减少到0
这么看的话,这是一道数学上的问题。如果这个数字的范围较小,在线性的时间内可以解决,我们可以选择采用动态规划来解决这个问题。
但是题目中这个数字的规模很大,有2*109 ,线性时间解决不了也存不下。
那么搜索也是一个好办法。不过搜索的复杂度非常高,我们需要对它进行一系列的优化:
仅进行前两部优化的算法还不足以在规定时间内完成任务,因此我们还需要继续进行优化。
class Solution {
static int ans = 1 << 30;
static HashMap<Integer,Integer> map = new HashMap();
private void dfs(int n,int k) {
if(k >= ans) {
return;
}
if(map.containsKey(n)) {
if(map.get(n) <= k) {
return;
}
}
map.put(n, k);
if(n == 0) {
ans = k;
return;
}
if(n % 3 == 0) {
dfs(n / 3,k + 1);
}
if(n % 2 == 0) {
dfs(n / 2,k + 1);
}
dfs(n - 1,k + 1);
}
public int minDays(int n) {
map.clear();
ans = 1 << 30;
dfs(n,0);
return ans;
}
}