1、题目1527:首尾相连数组的最大子数组和
时间限制:1 秒内存限制:128 兆特殊判题:否提交:1557解决:268
题目描述:
给定一个由N个整数元素组成的数组arr,数组中有正数也有负数,这个数组不是一般的数组,其首尾是相连的。数组中一个或多个连续元素可以组成一个子数组,其中存在这样的子数组arr[i],…arr[n-1],arr[0],…,arr[j],现在请你这个ACM_Lover用一个最高效的方法帮忙找出所有连续子数组和的最大值(如果数组中的元素全部为负数,则最大和为0,即一个也没有选)。
输入:
输入包含多个测试用例,每个测试用例共有两行,第一行是一个整数n(1=<n<=100000),表示数组的长度,第二行依次输入n个整数(整数绝对值不大于1000)。
输出:
对于每个测试用例,请输出子数组和的最大值。
样例输入:
6
1 -2 3 5 -1 2
5
6 -1 5 4 -7
样例输出:
10
14
来源:
淘宝2013年校园招聘一面面试题
解题思路:1、我看到其他人有在写,但是我觉得他们写的好像很复杂的样子。其实应该不难,暴力搜索的话,复杂度应该是O(N*N),将循环数组看成两个拼接起来的数组,然后针对每个i求最大连续子数组和。速度有点慢,可以参考其余大神们80ms的代码。
2、关于首尾相连数组的最大子数组和,这个有两种情况,1)、首尾不相连的数组中最大子数组和。2)、首尾相连的数组中,最大子数组和是所有数子和减去最小子数组和。这个时间复杂度是o(n),好像面试官会比较喜欢这种解题思路?
题目描述:
给定一个大小为n的数组,数组的元素a[i]代表第i天的股票价格。
设计一个算法,计算在最多允许买卖k次(一买一卖记为一次)的条件下的最大收益。
需要注意的是,你不能同时拥有两份股票。也就是说在下次买入前,你必须把手头上原有的股票先卖掉。
输入:
输入可能包含多个测试案例。
对于每个测试案例,输入的第一行为两个整数n和k(1<=n,k<=1000)。
输入的第二行包括n个整数,范围在[0,10000),代表数组中的元素。
输出:
对应每个测试案例,输出最大获益。
样例输入:
5 1
3 4 5 1 4
7 2
1 2 3 5 6 1 7
样例输出:
3
11
来源:
Leetcode 加强版本
解题思路:这个在 http://t.jobdu.com/thread-101867-1-1.html鬼M大神有写思路。
第j天交易i次的最大利润,dp[i][j]
dp[i][j] = max{dp[i-1][m]+price[j]-price[m]}(1 <= m < i);
dp[i-1][m]+a[j]-a[m]如果改写成
dp[i-1][m]-a[m]+a[j]
前面一部分dp[i-1][m]-a[m]和j是无关的
也就是说到dp[j]的时候,只要知道前面dp[i-1][m]-a[m]的最大值即可。
所以我们维护dp[i-1][m]-a[m]最大值。
题目描述:
输入包括多组测试数据,包括一个整数R(1<=R<=1000),和一个浮点数r(0<r<1),精确到第四位小数。
输出:
对于每组测试用例,输出一个浮点数,代表刀痕的长度,保留二位小数。
样例输入:
1000 0.5000
500 0.6183
样例输出:
1928.53
982.49
来源:
2014年王道论坛研究生机试练习赛(三)
解题思路:这个需要知道扇形面积计算公式,
1、s = |a|*R*R/2,其中R为半径,a为扇形对应的角度。二分查找,无限逼近。
2、假设切痕长度为mid,那么角度a = asin(mid/(2*R)),三角形面积为s1 = (mid/2)*sqrt(R*R-mid*mid/4);
3、则黄色部分的面积为l = s - s1,绿色部分面积为b = PI*R*R-l;
4、比例为l/b,如果l/R > r,则说明mid太大了,high = mid,否则的话low = mid;
题目描述:
计算机学院的男生和女生共n个人要坐成一排玩游戏,因为计算机的女生都非常害羞,男生又很主动,所以活动的组织者要求在任何时候,一个女生的左边或者右边至少有一个女生,即每个女生均不会只与男生相邻。现在活动的组织者想知道,共有多少种可选的座位方案。
例如当n为4时,共有
女女女女, 女女女男, 男女女女, 女女男男, 男女女男, 男男女女, 男男男男
7种。
输入:
输入包含多组测试用例,每组测试用例仅包含一个整数n(1<=n<=1000)。
输出:
对于每组测试用例,输出一个数代表可选的方案数,为防止答案过大,答案对1000000007取模。
样例输入:
1
2
4
样例输出:
1
2
7
来源:
2014年王道论坛研究生机试练习赛(三)
解题思路:这个好像是dp,dp[i] = dp[i-1] + dp[i-2] + dp[i-4]。
时间限制:1 秒内存限制:128 兆特殊判题:否提交:1557解决:268
题目描述:
给定一个由N个整数元素组成的数组arr,数组中有正数也有负数,这个数组不是一般的数组,其首尾是相连的。数组中一个或多个连续元素可以组成一个子数组,其中存在这样的子数组arr[i],…arr[n-1],arr[0],…,arr[j],现在请你这个ACM_Lover用一个最高效的方法帮忙找出所有连续子数组和的最大值(如果数组中的元素全部为负数,则最大和为0,即一个也没有选)。
输入:
输入包含多个测试用例,每个测试用例共有两行,第一行是一个整数n(1=<n<=100000),表示数组的长度,第二行依次输入n个整数(整数绝对值不大于1000)。
输出:
对于每个测试用例,请输出子数组和的最大值。
样例输入:
6
1 -2 3 5 -1 2
5
6 -1 5 4 -7
样例输出:
10
14
来源:
淘宝2013年校园招聘一面面试题
解题思路:1、我看到其他人有在写,但是我觉得他们写的好像很复杂的样子。其实应该不难,暴力搜索的话,复杂度应该是O(N*N),将循环数组看成两个拼接起来的数组,然后针对每个i求最大连续子数组和。速度有点慢,可以参考其余大神们80ms的代码。
2、关于首尾相连数组的最大子数组和,这个有两种情况,1)、首尾不相连的数组中最大子数组和。2)、首尾相连的数组中,最大子数组和是所有数子和减去最小子数组和。这个时间复杂度是o(n),好像面试官会比较喜欢这种解题思路?
1、Java AC
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
public class Main {
/*
* 1527
*/
public static void main(String[] args) throws Exception {
StreamTokenizer st = new StreamTokenizer(new BufferedReader(
new InputStreamReader(System.in)));
while (st.nextToken() != StreamTokenizer.TT_EOF) {
int n = (int) st.nval;
int len = 2 * n;
int array[] = new int[len];
for (int i = 0; i < n; i++) {
st.nextToken();
array[i] = (int) st.nval;
array[i + n] = array[i];
}
int sum = 0;
for (int i = 0; i < (i + n) && (i + n) <= len; i++) {
int tempSum = array[i];
if (tempSum > sum) {
sum = tempSum;
}
for (int j = i + 1; j < (i + n); j++) {
if (tempSum < 0) {
break;
} else {
tempSum += array[j];
}
if (tempSum > sum) {
sum = tempSum;
}
}
}
System.out.println(sum);
}
}
}
/**************************************************************
Problem: 1527
User: wangzhenqing
Language: Java
Result: Accepted
Time:1110 ms
Memory:25440 kb
****************************************************************/
1、C++ AC
#include <stdio.h>
const int maxn = 200002;
int n,i;
int array[maxn];
int main(){
while(scanf("%d",&n) != EOF){
int len = 2*n;
for(i = 0; i < n; i++){
scanf("%d",&array[i]);
array[i+n] = array[i];
}
int sum = 0;
for (i = 0; i < (i + n) && (i + n) <= len; i++) {
int tempSum = array[i];
if (tempSum > sum) {
sum = tempSum;
}
for (int j = i+1; j < (i + n ); j++) {
if (tempSum < 0) {
break;
}else {
tempSum += array[j];
}
if (tempSum > sum) {
sum = tempSum;
}
}
}
printf("%d\n",sum);
}
return 0;
}
/**************************************************************
Problem: 1527
User: wzqwsrf
Language: C++
Result: Accepted
Time:220 ms
Memory:1800 kb
****************************************************************/
2、Java AC
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
public class Main {
/*
* 1527
*/
public static void main(String[] args) throws Exception {
StreamTokenizer st = new StreamTokenizer(new BufferedReader(
new InputStreamReader(System.in)));
while (st.nextToken() != StreamTokenizer.TT_EOF) {
int n = (int) st.nval;
int array[] = new int[n];
int sum = 0;
st.nextToken();
array[0] = (int) st.nval;
sum += array[0];
int maxValue = array[0] > 0 ? array[0] : 0;
int minValue = array[0] < 0 ? array[0] : 0;
int max = maxValue;
int min = minValue;
for (int i = 1; i < n; i++) {
st.nextToken();
array[i] = (int) st.nval;
if (maxValue > 0) {
maxValue += array[i];
}else {
maxValue = array[i];
}
if (minValue < 0) {
minValue += array[i];
}else {
minValue = array[i];
}
max = maxValue > max ? maxValue : max;
min = minValue < min ? minValue : min;
sum += array[i];
}
int temp = sum - min;
System.out.println(max > temp ? max : temp);
}
}
}
/**************************************************************
Problem: 1527
User: wangzhenqing
Language: Java
Result: Accepted
Time:860 ms
Memory:28876 kb
****************************************************************/
2、C++ AC
#include <stdio.h>
const int maxn = 100002;
int n,i;
int array[maxn];
int main(){
while(scanf("%d",&n) != EOF){
scanf("%d",&array[0]);
int sum = 0;
sum += array[0];
int maxValue = array[0] > 0 ? array[0] : 0;
int minValue = array[0] < 0 ? array[0] : 0;
int max = maxValue;
int min = minValue;
for(i = 1; i < n; i++){
scanf("%d",&array[i]);
if (maxValue > 0) {
maxValue += array[i];
}else {
maxValue = array[i];
}
if (minValue < 0) {
minValue += array[i];
}else {
minValue = array[i];
}
max = maxValue > max ? maxValue : max;
min = minValue < min ? minValue : min;
sum += array[i];
}
int temp = sum - min;
printf("%d\n",max > temp ? max : temp);
}
return 0;
}
/**************************************************************
Problem: 1527
User: wzqwsrf
Language: C++
Result: Accepted
Time:70 ms
Memory:1412 kb
****************************************************************/
2、
题目1537:买卖股票
时间限制:1 秒内存限制:128 兆特殊判题:否提交:461解决:117
题目描述:
给定一个大小为n的数组,数组的元素a[i]代表第i天的股票价格。
设计一个算法,计算在最多允许买卖k次(一买一卖记为一次)的条件下的最大收益。
需要注意的是,你不能同时拥有两份股票。也就是说在下次买入前,你必须把手头上原有的股票先卖掉。
输入:
输入可能包含多个测试案例。
对于每个测试案例,输入的第一行为两个整数n和k(1<=n,k<=1000)。
输入的第二行包括n个整数,范围在[0,10000),代表数组中的元素。
输出:
对应每个测试案例,输出最大获益。
样例输入:
5 1
3 4 5 1 4
7 2
1 2 3 5 6 1 7
样例输出:
3
11
来源:
Leetcode 加强版本
解题思路:这个在 http://t.jobdu.com/thread-101867-1-1.html鬼M大神有写思路。
第j天交易i次的最大利润,dp[i][j]
dp[i][j] = max{dp[i-1][m]+price[j]-price[m]}(1 <= m < i);
dp[i-1][m]+a[j]-a[m]如果改写成
dp[i-1][m]-a[m]+a[j]
前面一部分dp[i-1][m]-a[m]和j是无关的
也就是说到dp[j]的时候,只要知道前面dp[i-1][m]-a[m]的最大值即可。
所以我们维护dp[i-1][m]-a[m]最大值。
Java AC
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
public class Main {
/*
* 1537
*/
public static void main(String[] args) throws Exception{
StreamTokenizer st = new StreamTokenizer(
new BufferedReader(new InputStreamReader(System.in)));
while (st.nextToken() != StreamTokenizer.TT_EOF) {
int n = (int) st.nval;
st.nextToken();
int k = (int) st.nval;
int array[] = new int[n+1];
for (int i = 1; i < n+1; i++) {
st.nextToken();
array[i] = (int) st.nval;
}
int size = 1002;
int dp[][] = new int[size][size];
int result = 0;
int tempValue = Integer.MIN_VALUE;
for (int i = 1; i < k+1; i++) {
tempValue = dp[i-1][1] - array[1];
for (int j = 2; j < n+1; j++) {
dp[i][j] = Math.max(tempValue+array[j], dp[i][j-1]);
result = Math.max(dp[i][j], result);
tempValue = Math.max(tempValue, dp[i-1][j]-array[j]);
}
}
System.out.println(result);
}
}
}
/**************************************************************
Problem: 1537
User: wangzhenqing
Language: Java
Result: Accepted
Time:600 ms
Memory:71720 kb
****************************************************************/
C++ AC
#include <stdio.h>
#include <string.h>
const int maxn = 1002;
int array[maxn];
int dp[maxn][maxn];
int max(int a, int b){
return a > b ? a : b;
}
int main(){
int n,k,i;
while(scanf("%d%d",&n,&k)!=EOF){
for(i = 1; i < n+1; i++){
scanf("%d",&array[i]);
}
memset(dp,0,sizeof(dp));
int result = 0;
int tempValue = 99999999;
for (i = 1; i < k+1; i++) {
tempValue = dp[i-1][1] - array[1];
for (int j = 2; j < n+1; j++) {
dp[i][j] = max(tempValue+array[j], dp[i][j-1]);
result = max(dp[i][j], result);
tempValue = max(tempValue, dp[i-1][j]-array[j]);
}
}
printf("%d\n", result);
}
return 0;
}
/**************************************************************
Problem: 1537
User: wzqwsrf
Language: C++
Result: Accepted
Time:90 ms
Memory:4948 kb
****************************************************************/
3、题目1551:切蛋糕
时间限制:1 秒内存限制:128 兆特殊判题:否提交:211解决:59
题目描述:
有如下图半价为R的圆形蛋糕,被切一刀后(图中红色直线),分成两个部分(黄色和绿色),已知其比例为r,求刀痕长度(图中红色直线)。
输入包括多组测试数据,包括一个整数R(1<=R<=1000),和一个浮点数r(0<r<1),精确到第四位小数。
输出:
对于每组测试用例,输出一个浮点数,代表刀痕的长度,保留二位小数。
样例输入:
1000 0.5000
500 0.6183
样例输出:
1928.53
982.49
来源:
2014年王道论坛研究生机试练习赛(三)
解题思路:这个需要知道扇形面积计算公式,
1、s = |a|*R*R/2,其中R为半径,a为扇形对应的角度。二分查找,无限逼近。
2、假设切痕长度为mid,那么角度a = asin(mid/(2*R)),三角形面积为s1 = (mid/2)*sqrt(R*R-mid*mid/4);
3、则黄色部分的面积为l = s - s1,绿色部分面积为b = PI*R*R-l;
4、比例为l/b,如果l/R > r,则说明mid太大了,high = mid,否则的话low = mid;
Java AC
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
public class Main {
/*
* 2014年3月9日 22:55:47
*/
public static void main(String[] args) throws IOException {
StreamTokenizer st = new StreamTokenizer(new BufferedReader(
new InputStreamReader(System.in)));
while (st.nextToken() != StreamTokenizer.TT_EOF) {
int R = (int) st.nval;
st.nextToken();
double r = st.nval;
double low = 0.0;
double high = 2 * R;
double mid = 0;
while ((high - low) >= 0.0001) {
mid = (low + high) / 2;
if (countArea(R, mid) > r) {
high = mid;
} else {
low = mid;
}
}
System.out.printf("%.2f\n", mid);
}
}
public static double countArea(double R, double mid) {
double du = Math.asin(mid / (2 * R));
double l = R * R * du - 0.5 * mid * Math.sqrt(R * R - 0.25 * mid * mid);
double r = R * R * Math.PI - l;
return l / r;
}
}
/**************************************************************
Problem: 1551
User: wzqwsrf
Language: Java
Result: Accepted
Time:380 ms
Memory:15160 kb
****************************************************************/
C++ AC
#include <stdio.h>
#include <math.h>
#define PI 3.1415926
double countArea(double R, double mid) {
double du = asin(mid / (2 * R));
double l = R * R * du - 0.5 * mid * sqrt(R * R - 0.25 * mid * mid);
double r = R * R * PI - l;
return l / r;
}
int main(){
int R;
double r;
while(scanf("%d%lf",&R,&r)!=EOF){
double low = 0.0;
double high = 2 * R;
double mid = 0;
while ((high - low) >= 0.0001) {
mid = (low + high) / 2;
if (countArea(R, mid) > r) {
high = mid;
} else {
low = mid;
}
}
printf("%.2lf\n", mid);
}
return 0;
}
/**************************************************************
Problem: 1551
User: wzqwsrf
Language: C++
Result: Accepted
Time:0 ms
Memory:1100 kb
****************************************************************/
4、题目1552:座位问题
时间限制:1 秒内存限制:128 兆特殊判题:否提交:208解决:51
题目描述:
计算机学院的男生和女生共n个人要坐成一排玩游戏,因为计算机的女生都非常害羞,男生又很主动,所以活动的组织者要求在任何时候,一个女生的左边或者右边至少有一个女生,即每个女生均不会只与男生相邻。现在活动的组织者想知道,共有多少种可选的座位方案。
例如当n为4时,共有
女女女女, 女女女男, 男女女女, 女女男男, 男女女男, 男男女女, 男男男男
7种。
输入:
输入包含多组测试用例,每组测试用例仅包含一个整数n(1<=n<=1000)。
输出:
对于每组测试用例,输出一个数代表可选的方案数,为防止答案过大,答案对1000000007取模。
样例输入:
1
2
4
样例输出:
1
2
7
来源:
2014年王道论坛研究生机试练习赛(三)
解题思路:这个好像是dp,dp[i] = dp[i-1] + dp[i-2] + dp[i-4]。
Java AC
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
public class Main {
/*
* 2014年3月9日 21:05:41
*/
public static void main(String[] args) throws IOException {
StreamTokenizer st = new StreamTokenizer(new BufferedReader(
new InputStreamReader(System.in)));
while (st.nextToken() != StreamTokenizer.TT_EOF) {
int n = (int) st.nval;
long dp[] = new long[1002];
int mod = 1000000007;
dp[1] = 1;
dp[2] = 2;
dp[3] = 4;
dp[4] = 7;
for (int i = 5; i <= n; i++) {
dp[i] = (dp[i-1] + dp[i-2] + dp[i-4]) % mod;
}
System.out.println(dp[n]);
}
}
}
/**************************************************************
Problem: 1552
User: wzqwsrf
Language: Java
Result: Accepted
Time:440 ms
Memory:17796 kb
****************************************************************/
C++ AC
#include <stdio.h>
#include <string.h>
const int maxn = 1002;
long dp[maxn];
int main(){
int mod = 1000000007;
dp[1] = 1;
dp[2] = 2;
dp[3] = 4;
dp[4] = 7;
for (int i = 5; i <= 1000; i++) {
dp[i] = (dp[i-1] + dp[i-2] + dp[i-4]) % mod;
}
int n;
while(scanf("%d",&n)!=EOF){
printf("%d\n", dp[n]);
}
return 0;
}
/**************************************************************
Problem: 1552
User: wzqwsrf
Language: C++
Result: Accepted
Time:0 ms
Memory:1028 kb
****************************************************************/