一:
度度熊想去商场买一顶帽子,商场里有N顶帽子,有些帽子的价格可能相同。度度熊想买一顶价格第三便宜的帽子,问第三便宜的帽子价格是多少?
输入描述:
首先输入一个正整数N(N <= 50),接下来输入N个数表示每顶帽子的价格(价格均是正整数,且小于等于1000)
输出描述:
如果存在第三便宜的帽子,请输出这个价格是多少,否则输出-1
输入例子:
10
10 10 10 10 20 20 30 30 40 40
输出例子:
30
解答:
public class Test1 {
public static int findThird(int[] a) //直接找第三大的数
{
Arrays.sort(a);
ArrayList<Integer> list=new ArrayList<>();
for(int i=0;i<a.length;i++)
{
if(!list.contains(a[i]))
list.add(a[i]);
}
if(list.size()<=2)
return -1;
else
return list.get(2);
}
public static int findThird1(int[] a)//利用集合的性质找出第三大的数
{
Arrays.sort(a);
TreeSet<Integer> t=new TreeSet<>();
for(int i=0;i<a.length;i++)
{
t.add(a[i]);
}
/*Iterator<Integer> it=t.iterator();
while(it.hasNext())
{
System.out.print(it.next()+" ");
}*/
if(t.size()<=2)
return -1;
return (int)t.toArray()[2];
}
public static int partition(int[] a,int low,int high)//利用剑指Offer上的找第三大的数的方法,利用快排的思想
{
int temp=a[low];
int i=low;
int j=high;
if(low<high)
{
while(i<j)
{
while(i<j&&a[j]>=temp) j--;
if(i<j)
{
a[i]=a[j];
i++;
}
while(i<j&&a[i]<=temp) i++;
if(i<j)
{
a[j]=a[i];
j--;
}
}
a[i]=temp;
return i;
}
return -1;
}
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
while(sc.hasNext()){
int N=sc.nextInt();
int[] a=new int[N];
for(int i=0;i<a.length;i++)
{
a[i]=sc.nextInt();
}
//System.out.println(findThird1(a));
int low=0;
int high=a.length-1;
int index=partition(a,low,high);
while(index!=2&&index!=-1)
{
if(index>2)
{
high=index-1;
index=partition(a,low,high);
}
else if(index<2)
{
low=index+1;
index=partition(a,low,high);
}
}
if(index==-1)
{
System.out.println(-1);
}
else
System.out.println(a[index]);
}
}
}
一个数轴上共有N个点,第一个点的坐标是度度熊现在位置,第N-1个点是度度熊的家。现在他需要依次的从0号坐标走到N-1号坐标。
但是除了0号坐标和N-1号坐标,他可以在其余的N-2个坐标中选出一个点,并直接将这个点忽略掉,问度度熊回家至少走多少距离?
输入描述:
输入一个正整数N, N <= 50。
接下来N个整数表示坐标,正数表示X轴的正方向,负数表示X轴的负方向。绝对值小于等于100
输出描述:
输出一个整数表示度度熊最少需要走的距离。
输入例子:
4
1 4 -1 3
输出例子:
4
解答:直接根据题意模拟即可
public class Test2 {
public static int distance(int[] a)
{
int min=Integer.MAX_VALUE;
for(int j=1;j<a.length-1;j++){
int k=a[j];
a[j]=a[j-1];
int sum=0;
for(int i=0;i<a.length-1;i++)
{
sum=sum+Math.abs(a[i+1]-a[i]);
}
if(sum<min)
min=sum;
a[j]=k;
}
return min;
}
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
while(sc.hasNext()){
int N=sc.nextInt();
int[] a=new int[N];
for(int i=0;i<N;i++)
{
a[i]=sc.nextInt();
}
System.out.println(distance(a));
}
}
}
三:度度熊有一个N个数的数组,他想将数组从大到小排好序,但是萌萌的度度熊只会下面这个操作:
任取数组中的一个数然后将它放置在数组的最后一个位置。
问最少操作多少次可以使得数组从小到大有序?
输入描述:
首先输入一个正整数N,接下来的一行输入N个整数。(N <= 50, 每个数的绝对值小于等于1000)
输出描述:
输出一个整数表示最少的操作次数。
输入例子:
4
19 7 8 25
输出例子:
2
解答:转换为求排序之后与排序之前的公共前缀。然后用N减去公共前缀的长度,即可得到最少的操作次数
public class Test4 {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
while(sc.hasNext()){
int N=sc.nextInt();
int[] a=new int[N];
int[] sort=new int[N];
for(int i=0;i<a.length;i++)
{
a[i]=sc.nextInt();
sort[i]=a[i];
}
Arrays.sort(sort);
int i=0, j=0;
while(j<N)
{
if(a[j]==sort[i])
{
i++;
j++;
}
else
{
j++;
}
}
System.out.println(N-i);
}
}
}
四:
度度熊最近对全排列特别感兴趣,对于1到n的一个排列,度度熊发现可以在中间根据大小关系插入合适的大于和小于符号(即 '>' 和 '<' )使其成为一个合法的不等式数列。但是现在度度熊手中只有k个小于符号即('<'')和n-k-1个大于符号(即'>'),度度熊想知道对于1至n任意的排列中有多少个排列可以使用这些符号使其为合法的不等式数列。
输入描述:
输入包括一行,包含两个整数n和k(k < n ≤ 1000)
输出描述:
输出满足条件的排列数,答案对2017取模。
输入例子:
5 2
输出例子:
66解答:
p[i][j] = (dp[i - 1][j - 1] * (i - j) + dp[i - 1][j] * (j + 1)) % 2017;
dp[i][j]表示有i个数字及j个小于号所能组成的数量(大于号数量当然是i - j - 1次,后面需要使用)
而加入第i + 1个数字时,分以下四种情况:
1.如果将i+1插入当前序列的开头,即有了1<2,加入后成为3>1<2,会发现等于同时加入了一个大于号!(此时可以无视1与2之间的关系,因为i+1>i)
2.如果将i+1插入当前序列末尾,即1<2变成了 1<2<3,会发现等于同时加入了一个小于号!
(此时可以无视1与2之间的关系,因为i+1>i)
3.如果将i+1加入一个小于号之间,即已经有 1<2了,向中间加入3,会发现变成了1<3>2,等于同时加入了一个大于号!
4.如果将i+1加入一个大于号中间,即有了2>1,变成了2<3>1,等于同时加入了一个小于号!
综上所述,
dp[i][j]等于以上四种情况之和:
dp[i - 1][j] //将i加在开头等于加入一个大于号,即要求i-1个数时已经有了j个小于号
dp[i - 1][j - 1] //将i加在末尾等于加入一个小于号,即要求i-1个数时已经有了j-1个小于号
dp[i - 1][j] * j //将i加在任意一个小于号之间,等于加入了一个大于号;即要求i-1个数时已经有了j个小于号,每个小于 号都可以进行这样的一次插入
dp[i - 1][j - 1] * (i- j - 1) //将i加载任意一个大于号之间,等于加入了一个小于号;即要求i-1个数时有了j-1个小于号,而此时共有
(i - 1) - (j - 1)- 1个大于号,每个大于号都要进行一次这样的操作
合并同类项即为
dp[i][j] = (dp[i - 1][j - 1] * (i - j) + dp[i - 1][j] * (j + 1))
最后要记得取模
public class Test5 {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int k=sc.nextInt();
int[][] dp=new int[n+1][k+1];
for(int i=1;i<=n;i++)
dp[i][0]=1;
for(int i=2;i<=n;i++)
for(int j=1;j<=k;j++)
{
dp[i][j]=(dp[i-1][j-1]*(i-j)+dp[i-1][j]*(j+1))%2017;
}
System.out.println(dp[n][k]);
}
}