草庐IT

程序员进阶之算法练习(六十四)

落影loyinglin 2023-03-28 原文

题目1

题目链接
题目大意:
给出一个字符串(由26个大写字母组成),询问这个字符串中,是否相同的字母都连在一起。

输入:
第一行整数t,表示有t个样例(1≤?≤1000)
每个样例两行,第一行是整数n,表示字符串长度 (1≤?≤50)
第二行是字符串
输出:
如果满足要求,则输出YES;
如果不满足要求,则输出NO;

Examples
input
5
3
ABA
11
DDBBCCCBBEZ
7
FFGZZZY
1
Z
2
AB

output
NO
NO
YES
YES
YES

题目解析:
用一个数组记录已经出现的字符串,从左到右枚举字符串;
对于第i个字符,如果和第i-1个字符不相同,则判断是否出现过:
已出现过则不满足要求;
未出现则标识该字符已出现。

class Solution {
    static const int N = 100010;
public:
    int n, m;
    string str;
public:
    void solve() {
        int t;
        cin >> t;
        while (t--) {
            cin >> n;
            cin >> str;
            int a[256] = {0}, ok = 1;
            a[str[0]] = 1;
            for (int i = 1; i < n; ++i) {
                if (str[i] == str[i-1]) {
                    continue;;
                }
                else {
                    if (a[str[i]]) {
                        ok = 0;
                    }
                    else {
                        a[str[i]] = 1;
                    }
                }
            }
            if (ok) {
                cout << "YES" << endl;
            }
            else {
                cout << "NO" << endl;
            }
        }
    }
}
ac;

题目2

题目链接
题目大意:
给出一个数字n,求出[1,n]的区间中,有多少整数是可以满足,所有数字都是相同的。

输入:
第一行是整数t,表示有t个样例(1≤?≤1e4).
每个样例一行,第一行是整数n(1≤?≤1e9).
输出:
每个样例一行,输出1到n的整数中,有多少个由相同数字组成的数。

Examples
input
6
1
2
3
4
5
100

output
1
2
3
4
5
18

题目解析:
如果直接遍历数字1到n,可以算出来有多少个整数满足要求。
因为n比较比较大,这种做法会超时。
注意到满足要求的数字应该不多,我们可以直接满足要求的数字:
先看一位数的有多少个数字;
再看二位数的有多少个数字;
...
直到枚举出来的数字,比n还要大。

class Solution {
    static const int N = 100010;
public:
    int n, m;
    string str;
public:
    void solve() {
        int t;
        cin >> t;
        while (t--) {
            cin >> n;
            int ans = 0;
            int current = 1, cnt = 1;
            while (current * cnt <= n) {
                ++ans;
                ++cnt;
                if (cnt > 9) {
                    current = current * 10 + 1;
                    cnt = 1;
                }
            }
            cout << ans << endl;
        }
    }
}
ac;

题目3

题目链接
题目大意:
给出一个数字n,构造n * n的矩阵,要求:
相邻的数字,绝对值之差要大于1;
每个数字可以和上下左右,四个方向的数字相邻;
矩阵中的数字是1~n * n,没有重复;

输入:
第一行是整数t,表示有t个样例 (1≤?≤100).
每个样例第一行是整数? (1≤?≤100).
输出:
如果有解,则输出n行,每行n个整数;
如果无解则输出-1;

Examples
input
3
1
2
3

output
1
-1
2 9 7
4 6 3
1 8 5

题目解析:
1只有一个解,2无解;
从3开始,可以采用间隔的方式先填充数字;
1 0 2
0 3 0
4 0 5
如上,先从上到下,从左到右填充;
最后补齐
1 5 2
6 3 7
4 8 5
因为我们都是间隔着填充,相邻的数字只差,肯定大于1,满足要求。

class Solution {
    static const int N = 100010;
public:
    int n, m;
    int a[101][101];
public:
    void solve() {
        int t;
        cin >> t;
        while (t--) {
            cin >> n;
            if (n == 1) {
                cout << 1 << endl;
            }
            else if (n == 2) {
                cout << -1 << endl;
            }
            else {
                int cnt = 1, x = 0, y = 0;
                while (cnt <= n*n) {
                    a[x][y] = cnt;
                    ++cnt;
                    y += 2;
                    if (y >= n) {
                        x += 1;
                        y -= n;
                    }
                    if (x >= n) {
                        x = 0;
                        y = 1;
                    }
                }
                for (int i = 0; i < n; ++i) {
                    for (int j = 0; j < n; ++j) {
                        cout << a[i][j] << " ";
                    }
                    cout << endl;
                }
            }
        }
    }
}
ac;

题目4

题目链接
题目大意:
给出n个数字的数组,问数组中存在多少个(i, j)的组合,满足i<j 且 a[j]-a[i]=j-i;

输入:
第一行是整数t,表示t个样例(1≤?≤1e4).
每个样例有2行,第一行是整数n (1≤?≤2⋅1e5)
第二行是n个整数?1,?2,…,?? (1≤??≤?)

输出:
输出满足要求的组合数量。

Examples
input
4
6
3 5 1 4 6 6
3
1 2 3
4
1 3 3 4
6
1 6 3 4 5 6

output
1
3
3
10

题目解析:
将题目要求的 a[j]-a[i]=j-i 换一下位置,得到 (a[j] - j)= (a[i] - i);
那么将所有的数字,减去当前的位置,然后排序,即可知道每一组数字的数量;
每一组数字假设有k个,那么就有k*(k-1)/2的可能。

class Solution {
    static const int N = 200010;
public:
    int n, m;
    int a[N];
public:
    void solve() {
        int t;
        cin >> t;
        while (t--) {
            cin >> n;
            for (int i = 0; i < n; ++i) {
                cin >> a[i];
                a[i] -= i;
            }
            a[n] = 0;
            sort(a, a + n);
            lld ans = 0, cnt = 1;
            for (int i = 1; i<= n; ++i) {
                if (a[i] != a[i - 1]) {
                    ans += cnt * (cnt - 1) / 2;
                    cnt = 1;
                }
                else {
                    ++cnt;
                }
            }
            cout << ans << endl;
        }
    }
}
ac;

题目5

题目链接
题目大意:
给出长度为n的字符串,'*'表示绵羊, '.'表示空地;
每次可以把绵羊移动到相邻的空地,问需要移动多少次,才能将所有的绵羊赶在一起。

输入:
第一行是整数t,表示t个样例(1≤?≤1e4).
每个样例有2行,第一行是整数n (1≤?≤2⋅1e5)
第二行是字符串

输出:
最小的移动次数。

Examples
input

 5
 6
 **.*..
 5
 *****
 3
 .*.
 3
 ...
 10
 *.*...*.**

output
1
0
0
0
9

题目解析:
方法1:
暴力,假设羊最终集中在区间[left, right]上面,枚举left的位置,再用贪心从左到右匹配羊的位置。

方法2:
动态规划
dpLeft[i]表示,前i个位置中的所有羊,都集中在位置i左边;
dpRight[i]表示,[i, n]的位置中所有羊,都集中在位置i的右边;
这样只要得到结果之后,只要枚举每一个位置即可。

数据范围较大,没用long long 错了2次。

class Solution {
    static const int N = 1000010;
public:
    int n, m;
    string str;
    pair<lld, lld> dpLeft[N], dpRight[N]; // first 是最小代价,second的当前绵羊数量
public:
    void solve() {
        int t;
        cin >> t;
        while (t--) {
            cin >> n;
            cin >> str;
            dpLeft[0] = make_pair(0, 0);
            for (int i = 1; i <= n; ++i) {
                char c = str[i - 1];
                if (c == '*') {
                    dpLeft[i].first = dpLeft[i-1].first;
                    dpLeft[i].second = dpLeft[i-1].second + 1;
                }
                else {
                    dpLeft[i].first = dpLeft[i-1].first + dpLeft[i-1].second;
                    dpLeft[i].second = dpLeft[i-1].second;
                }
            }
            dpRight[n+1] = make_pair(0, 0);
            for (int i = n; i > 0; --i) {
                char c = str[i - 1];
                if (c == '*') {
                    dpRight[i].first = dpRight[i+1].first;
                    dpRight[i].second = dpRight[i+1].second + 1;
                }
                else {
                    dpRight[i].first = dpRight[i+1].first+dpRight[i+1].second;
                    dpRight[i].second = dpRight[i+1].second;
                }
            }
            lld ans = dpRight[1].first;
            for (int i = 0; i <= n; ++i) {
                ans = min(ans, dpLeft[i].first + dpRight[i + 1].first);
            }
            cout << ans << endl;
        }
    }
}
ac;

有关程序员进阶之算法练习(六十四)的更多相关文章

  1. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  2. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  3. ruby - 在 Ruby 中编写命令行实用程序 - 2

    我想用ruby​​编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序

  4. ruby-on-rails - Rails 应用程序之间的通信 - 2

    我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

  5. ruby - 无法运行 Rails 2.x 应用程序 - 2

    我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby​​:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r

  6. ruby-on-rails - Rails 应用程序中的 Rails : How are you using application_controller. rb 是新手吗? - 2

    刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr

  7. ruby-on-rails - 如何在我的 Rails 应用程序 View 中打印 ruby​​ 变量的内容? - 2

    我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby​​中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R

  8. ruby - 检查是否通过 require 执行或导入了 Ruby 程序 - 2

    如何检查Ruby文件是否是通过“require”或“load”导入的,而不是简单地从命令行执行的?例如:foo.rb的内容:puts"Hello"bar.rb的内容require'foo'输出:$./foo.rbHello$./bar.rbHello基本上,我想调用bar.rb以不执行puts调用。 最佳答案 将foo.rb改为:if__FILE__==$0puts"Hello"end检查__FILE__-当前ruby​​文件的名称-与$0-正在运行的脚本的名称。 关于ruby-检查是否

  9. ruby-on-rails - 如何在 Gem 中获取 Rails 应用程序的根目录 - 2

    是否可以在应用程序中包含的gem代码中知道应用程序的Rails文件系统根目录?这是gem来源的示例:moduleMyGemdefself.included(base)putsRails.root#returnnilendendActionController::Base.send:include,MyGem谢谢,抱歉我的英语不好 最佳答案 我发现解决类似问题的解决方案是使用railtie初始化程序包含我的模块。所以,在你的/lib/mygem/railtie.rbmoduleMyGemclassRailtie使用此代码,您的模块将在

  10. 程序员如何提高代码能力? - 2

    前言作为一名程序员,自己的本质工作就是做程序开发,那么程序开发的时候最直接的体现就是代码,检验一个程序员技术水平的一个核心环节就是开发时候的代码能力。众所周知,程序开发的水平提升是一个循序渐进的过程,每一位程序员都是从“菜鸟”变成“大神”的,所以程序员在程序开发过程中的代码能力也是根据平时开发中的业务实践来积累和提升的。提高代码能力核心要素程序员要想提高自身代码能力,尤其是新晋程序员的代码能力有很大的提升空间的时候,需要针对性的去提高自己的代码能力。提高代码能力其实有几个比较关键的点,只要把握住这些方面,就能很好的、快速的提高自己的一部分代码能力。1、多去阅读开源项目,如有机会可以亲自参与开源

随机推荐