目录
一:统计是给定字符串前缀的字符串数目
给你一个字符串数组 words
和一个字符串 s
,其中 words[i]
和 s
只包含 小写英文字母 。
请你返回 words
中是字符串 s
前缀 的 字符串数目 。
一个字符串的 前缀 是出现在字符串开头的子字符串。子字符串 是一个字符串中的连续一段字符序列。
示例:
输入:words = ["a","b","c","ab","bc","abc"], s = "abc" 输出:3 解释: words 中是 s = "abc" 前缀的字符串为: "a" ,"ab" 和 "abc" 。 所以 words 中是字符串 s 前缀的字符串数目为 3 。
总结:首先说一下自己的想法。双层for循环,由于是判断words中是s前缀和,因此肯定是先遍历words(从第一个开始,一直到最后一个,看看他们是否是s的前缀),然后遍历s(根据前缀的定义,循环从0开始,直到字符串结束,遍历的意义是字符串s结束的位置)。在两层for训话之内判断他们是否相等即可。
开始做的时候有点问题:开始用的是==判断是否相等,当然,结果你们懂的。。。然后改用equals()方法。完成。实在是把基础语法都给忘记了,Java中判断两个字符串是否相等,不能使用==,这样他们判断的是两个对象的地址是否相等,即是不是同一个对象。equals()方法只是简单的判断内容是否相等。
public static int countPrefixes(String[] words, String s) {
int count = 0;
for (int i = 0; i < words.length; i++) {//i为words中的第几个
for (int j = 0; j < s.length(); j++) {
if (words[i].equals(s.substring(0, j + 1))) {
count++;
break;
}
}
}
return count;
}
二、乘积
给定一个数组a_1,a_2,a_3,...,a_na1,a2,a3,...,an,问有多少个(i,j,k)(i<j<k)(i,j,k)(i<j<k),使得ai * aj * ak 乘积最小
输入格式
第一行包含一个n(3≤n≤105 ),表示数组的长度
第二行包含nn个正整数ai(1≤ai≤109)表示给定数组的元素
输出格式
打印一个数字 — 三元组(i,j,k)的数量,使得i,j,ki,j,k成对不同并且ai×aj×ak是可能的最小值。
输入 #1
4 1 1 1 1
输出 #1
4
输入 #2
5 1 3 2 3 4
输出 #2
2
想法:刚开始想着,直接排序,然后循环,不太对。后来也是分类讨论情况,但是并没有将所有的情况讨论完整,然后也有点乱乱的感觉。
说一下正确思路:首先肯定是排序。毕竟排序后所有小的数字都在前面。
(1)如果第一个小的数的个数count1>=3,则直接从count1中选3个。count1*(count1-1)*(count1-2)/3!
(2)如果第一个小的数的个数count1<3,此时求第二个小的数的个数count2,如果count1+count2>=3,此时分两种情况{第一种:count1=1,结果为:count2*(count2-1)/2,第二种情况为:count1=2,此时结果为:count2}
(3)第一个数的个数count1+第二个小的数的个数count2<3,结果为:count3
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n=sc.nextInt();
long[] arr = new long[n+1];
for (int i = 1; i <=n; i++) {
arr[i]=sc.nextLong();
}
Arrays.sort(arr);//首先对数组排序
int pos=-1;
for (int i = 1; i <=n ; i++) {
if(arr[1]==arr[i]){
pos=i;
}else {
break;
}
}
//此时的pos即为第一个小的数字的个数
if(pos>=3){
System.out.println(pos*(pos-1)*(pos-2)/6);
}else {
int k=3-pos;//前三个数的剩余位置
int pos2=-1;
for (int i = pos+1; i <=n ; i++) {
if(arr[pos+1]==arr[i]){
pos2=i;
}else {
break;
}
}
//此时,pos2-pos的值即为第二个小的数的个数
if(pos2-pos>=k){//如果前两个小的数字的个数超过3
if(k==2){//k为2,意味着第一个小的数字个数为1
System.out.println((pos2-pos)*(pos2-pos-1)/2);
}else{
System.out.println(pos2-pos);
}
}else {//前两个小的数字个数之和<3
int pos3=-1;
for (int i = pos2+1; i <=n ; i++) {
if(arr[pos2+1]==arr[i]){
pos3=i;
}else {
break;
}
}
System.out.println(pos3-pos2);
}
}
}
三、找数字
给定一个长度为 n 的数组 a,其中只有一个数字只出现 1 次,其余均为 2 次,请你求出出现一次的数字 。
输入格式
第一行一个整数 n,保证 n 是一个奇数 。 接下来 n 行 n个整数 a1, a2,…… an
输出格式
一行一个整数表示答案。
说明/提示
数据范围1≤n≤2×107+1,ai≤109
保证 n 是一个奇数
本题数据范围过大,请使用 C++C++ 等高效的语言。
思路分析:由于数据范围过大,因此,使用暴力时间复杂度为:O(nlogn)。
如果使用异或运算,则时间复杂度仅为O(n)。
为什么使用异或运算呢?当然不是我这个菜鸡能想到的了。异或运算:相同的值异或结果为0,而0与任何数字异或,还是那个数字本身。
这样异或一遍之后,得到的结果即为最终的只出现了一次的数字
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n=sc.nextInt();
long ans=0;
for (int i = 0; i <n ; i++) {
ans=ans^=sc.nextLong();
}
System.out.println(ans);
}
四、阿尔法星球
阿尔法星球是一个偶数星球,也就是说他的数字出现都是成对的,例如315和321是一个阿尔法数对。
题目描述
阿尔法星球对于阿尔法数对有一个新的大小定义关系,对于数对的第一个数,依旧是谁大,数对就大;如果第一个数相同,看第二个数模7的余数谁大,数对就更大。
输入格式
第一行一个整数n,表示有n个阿尔法数对;
第二行n个正整数,表示n个阿尔法数对的第一个数。
第三行n个正整数,表示n个阿尔法数对的第二个数。
输出格式
输出从小到大排序后阿尔法数对的第二个数。
输出一行,数之间用空格隔开。
输入输出样例
输入 #1
4 1 1 1 1 4 5 6 7
输出 #1
7 4 5 6
n小于等于100000。
思路分析:首先当时一直没有想到该怎么写,后来看了答案才知道,原来自己是真的不会。不过不会就学嘛,学会了就会了。主要是进行结构体的排序,重写cmp()函数
通过该题知道了原来结构体还能直接struct{}a[10000]这样定义一个结构体类型的数组,并且数组的长度为一个常数。
#include <bits/stdc++.h>
using namespace std;
int n;
struct Node{
int first;
int second;
}a[100000];
bool cmp(Node &a,Node &b){
if(a.first==b.first){
return a.second%7<b.second%7;
}else{
return a.first<b.first;
}
}
int main()
{
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i].first;
}
for(int i=0;i<n;i++){
cin>>a[i].second;
}
sort(a,a+n,cmp);
for(int i=0;i<n;i++){
cout<<a[i].second<<endl;
}
return 0;
}