【九度】题目1422:Closest Number

108 篇文章 0 订阅
11 篇文章 0 订阅
题目1422:Closest Number
时间限制:10 秒内存限制:64 兆特殊判题:否提交:690解决:136
题目描述:
        There is one Master In ACM_DIY called "白衣少年"(White) whose motto is "I can HOLD ANY FEMALE". Since White is really busy with HOLDING FEMALES, he has no idea of the work that is given by his boss(MALE, of course), so can you help him to solve such a simple and really easy problem: 
        Array A has N positive integers,for each A[i] (0<=i<N, indicating the i-th integer in the array A), it fits in a 32-bit signed integer ),find the closest number less than A[i] (if the distance is the same,we prefer the left one).
        If you can solve this problem, White may give you some "tips"(You know better!)
输入:
        T cases (1<=T<=5)
        For each case, the first line give an integer N(1<= N <= 10^6),then the second line has the array with N integers. (All the integers are guaranteed to fit in 32-bit signed integer)
输出:
        For each case, print one line with N space-seperated integers, where the i-th integer is the number who is less that A[i] and is closest to i if exists, otherwise it is 0. 
样例输入:
3
3
2 1 3
3
2 3 1
4
5 7 3 6
样例输出:
1 0 1
1 2 0
3 5 0 3
来源:
第四届ACM_DIY群程序设计竞赛
解题思路:
        这个题目的意思是,问每个数离它最近的比它小的数是多少。
        思想上有点像动态规划。
        基本思想是从左求解一次,从右求解一次。
        从左求解的是,所有左边比它小的数。
        从右求解的是,所有右边比它小的数。
        比如从左到右求解,每次针对i求解的时候,判断它左边的数是不是比它小,如果比它小,就是它了,否则就一直判断知道1为止,这个会超时,剪枝就是递归求解。

Java AC

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
 
public class Main {
    /*
     * 2014年3月26日 19:04:04
     */
    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 T = (int) st.nval;
            while (T > 0) {
                st.nextToken();
                int n = (int) st.nval;
                int array[] = new int[n + 2];
                int dp1[] = new int[n + 1];
                int dp2[] = new int[n + 1];
                for (int i = 1; i <= n; i++) {
                    st.nextToken();
                    array[i] = (int) st.nval;
                    dp1[i] = i - 1;
                    dp2[i] = i + 1;
                }
                array[0] = array[n+1] = Integer.MIN_VALUE;
                startToEnd(array, dp1, n);
                endToStart(array, dp2, n);
 
                StringBuffer sb = new StringBuffer();
                for (int i = 1; i <= n; i++) {
                    if (dp1[i] == 0 && dp2[i] == n+1) {
                        sb.append(0 + " ");
                    } else if (dp1[i] == 0) {
                        sb.append(array[dp2[i]] + " ");
                    } else if (dp2[i] == n+1) {
                        sb.append(array[dp1[i]] + " ");
                    } else {
                        int temp = (i - dp1[i]) == (dp2[i] - i) ? dp1[i]
                                : ((i - dp1[i]) < (dp2[i] - i) ? dp1[i]
                                        : dp2[i]);
                        sb.append(array[temp] + " ");
                    }
                     
                }
                System.out.println(sb.toString().trim());
                T--;
            }
        }
    }
 
    private static void endToStart(int[] array, int[] dp, int n) {
        for (int i = n; i > 0; i--) {
            int temp = dp[i];
            while (temp != n+1 && array[i] <= array[temp]) {
                temp = dp[temp];
            }
            dp[i] = temp;
        }
    }
 
    private static void startToEnd(int[] array, int[] dp, int n) {
        for (int i = 1; i <= n; i++) {
            int temp = dp[i];
            while (temp != 0 && array[i] <= array[temp]) {
                temp = dp[temp];
            }
            dp[i] = temp;
        }
    }
}
 
/**************************************************************
    Problem: 1422
    User: wzqwsrf
    Language: Java
    Result: Accepted
    Time:2460 ms
    Memory:191660 kb
****************************************************************/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值