算法训练#15:Déjà Vu(暴力)和And Then There Were K(贪心)

40 阅读3分钟

“开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 18 天,点击查看活动详情

第一题

Déjà Vu

题目理解

给出一个字符串(不知道是否为回文串),要求判断以下情况:

  1. 若可以通过插入一个字符“a”使其不是回文串,则输出“YES”
  2. 否则输出“NO”

回文串:把字符串倒转仍然与原来的字符串相同

输入

输入整数tt,代表案例个数,1t1041\le t\le 10^{4}
每个案例输入一个字符串s

输出

看上方题目理解

思路

这里若要在随意位置添加一个“a”,我们要考虑以下情况:

  1. 本来是回文串,添加字符后要其不是回文串
  2. 本来不是回文串,添加字符后其仍然不是回文串
  3. 本来是回文串,添加字符后其不是回文串
  4. 本来是回文串,添加字符后其仍然是回文串

若要思考这些复杂的问题,这道题可就困难多了,所以把问题想的简单一点:若原来是回文串,那么我们只需要在字符串左右两端添加“a”就可以使部分回文串不再是回文串(两端添加仍是回文串的情况参考“aaaaa”),那本来就不是回文串的情况亦是如此,所以我们只需要固定的在头尾两端其中之一添加“a”,然后再进行回文串的判定,从而输出结果即可

代码

import java.util.Scanner;

public class dejavu {

    public static void main(String args[]) {
        Scanner sc = new Scanner(System.in);
        int t;
        t = sc.nextInt();
        for (int i = 0; i < t; i++)//操作次数
        {
            String s=sc.next();
            String ans1="a"+s;
            String ans2=s+"a";
            if(!palindrome(ans1))
            {
                System.out.println("YES");
                System.out.println(ans1);
            }
            else if(!palindrome(ans2))
            {
                System.out.println("YES");
                System.out.println(ans2);
            }
            else
            {
                System.out.println("NO");
            }
        }
    }
    public static  boolean palindrome(String s)//回文判定
    {
        int mid=s.length()/2;
        int n=s.length()-1;
        if(s.charAt(0)!=s.charAt(n))//因为添加了“a”,所以用这个比较快一点
        {
            return false;
        }
        for(int i=1;i<mid;i++)
        {
            if(!s.substring(i,i+1).equals(s.substring(n-i,n-i+1)))//双指针逐步判定
            {
                return false;
            }
        }
        return true;
    }

}

第二题

And Then There Were K

题目理解

给出一个整数n,若有n&(n1)&(n2)&k=0 n\&(n-1)\&(n-2)\cdots\&k=0,则需要我们找出k这个数

输入

输入整数tt,代表案例个数,1t3×1041\le t\le 3\times 10^{4}
每个案例输入一个整数xx,其中1t1091\le t\le 10^{9}

输出

输出一个整数kk

思路

首先很容易想到用模拟来解决这个问题,因为按位与运算的过程只需要用一个 & 号就能解决,但是xx的取值范围到了 10910^{9},就算是ono(n)的时间复杂度也顶不住,所以我们要另寻出路,寻找这个按位与的过程的规律。我们知道与其实就是只有两边都是1这一位才能是1,所以说按照题目这样一直与下去,结果肯定会越来越小(因为越来越多的0出现),所以肯定成立,那么到最后一次与运算应该在哪里结束呢?,我们不妨这样想想:若2ax<2a+12^{a}\le x \lt2^{a+1} 因为2a2^{a}除了第一位全是0,肯定可以消掉大多数0,而2a12^{a}-1又可以消掉2a2^{a}第一位的1,所以我们只需要找到尽量大的2a2^{a},然后把2a12^{a}-1作为答案,一切就不用担心那么多了

代码

import java.util.Scanner;

public class ATTWK {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int t;
        t = sc.nextInt();
        for (int i = 0; i < t; i++) {
            int x = sc.nextInt();
            int y = 1;
            while (y * 2 <= x) {
                y = y * 2;
            }
            System.out.println(y - 1);
        }
    }
}