今日份算法总结

目录

一:统计是给定字符串前缀的字符串数目

二、乘积

三、找数字

四、阿尔法星球

一:统计是给定字符串前缀的字符串数目

给你一个字符串数组 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;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值