How to print the pythagorean triple with the largest hypotenuse - pythagorean

I have to find all the pythagorean triples which have a value of "c" (where c is the hypotenuse) smaller than an integer number entered by the user. I was able to do this, however I also have to print which triple has the largest value of "c".
# include <stdio.h>
int main()
{
int i=1, N, a, b, c;
printf("Please enter an integer number: ");
scanf("%d", &N);
for(c=1; c<N; c++)
{
for(b=1; b<c; b++)
{
for(a=1; a<b; a++)
{
if((a*a)+(b*b)==(c*c))
{
printf("\n%d.(%d,%d,%d)\n", i++, a, b, c);
}
}
}
}
printf("\nThere are %d triples which contain a c<N.\n\n", (i++)-1);
system("PAUSE");
return(0);
}

You can have a variable to remember the largest c. Below commented lines are added, take a look:
int largest_c = 0; //define it
for(c=1; c<N; c++)
{
for(b=1; b<c; b++)
{
for(a=1; a<b; a++)
{
if((a*a)+(b*b)==(c*c))
{
if (c > largest_c) { //found a bigger one, so remember it
largest_c = c;
}
printf("\n%d.(%d,%d,%d)\n", i++, a, b, c);
}
}
}
}
By the way, with a small trick, you can easily speed up your algorithm: any time, you found a^2 + b^2 >= c^2, you can immediately skip the rest for the most inner loop. There are other things you can do to speed up the algorithm further.

Related

Palindrome operations on a string

You are given a string S initially and some Q queries. For each query you will have 2 integers L and R. For each query, you have to perform the following operations:
Arrange the letters from L to R inclusive to make a Palindrome. If you can form many such palindromes, then take the one that is lexicographically minimum. Ignore the query if no palindrome is possible on rearranging the letters.
You have to find the final string after all the queries.
Constraints:
1 <= length(S) <= 10^5
1 <= Q <= 10^5
1<= L <= R <= length(S)
Sample Input :
4
mmcs 1
1 3
Sample Output:
mcms
Explanation:
The initial string is mmcs, there is 1 query which asks to make a palindrome from 1 3, so the palindrome will be mcm. Therefore the string will mcms.
If each query takes O(N) time, the overall time complexity would be O(NQ) which will give TLE. So each query should take around O(logn) time. But I am not able to think of anything which will solve this question. I think since we only need to find the final string rather than what every query result into, I guess there must be some other way to approach this question. Can anybody help me?
We can solve this problem using Lazy Segment Tree with range updates.
We will make Segment Tree for each character , so there will be a total of 26 segment trees.
In each node of segment tree we will store the frequency of that character over the range of that node and also keep a track of whether to update that range or not.
So for each query do the following ->
We are given a range L to R
So first we will find frequency of each character over L to R (this will take O(26*log(n)) time )
Now from above frequencies count number of characters who have odd frequency.
If count > 1 , we cannot form palindrome, otherwise we can form palindrome
If we can form palindrome then,first we will assign 0 over L to R for each character in Segment Tree and then we will start from smallest character and assign it over (L,L+count/2-1) and (R-count/2+1,R) and then update L += count/2 and R -= count/2
So the time complexity of each query is O(26log(n)) and for building Segment Tree time complexity is O(nlog(n)) so overall time complexity is O(nlogn + q26logn).
For a better understanding please see my code,
#include <bits/stdc++.h>
using namespace std;
#define enl '\n'
#define int long long
#define sz(s) (int)s.size()
#define all(v) (v).begin(),(v).end()
#define input(vec) for (auto &el : vec) cin >> el;
#define print(vec) for (auto &el : vec) cout << el << " "; cout << "\n";
const int mod = 1e9+7;
const int inf = 1e18;
struct SegTree {
vector<pair<bool,int>>lazy;
vector<int>cnt;
SegTree () {}
SegTree(int n) {
lazy.assign(4*n,{false,0});
cnt.assign(4*n,0);
}
int query(int l,int r,int st,int en,int node) {
int mid = (st+en)/2;
if(st!=en and lazy[node].first) {
if(lazy[node].second) {
cnt[2*node] = mid - st + 1;
cnt[2*node+1] = en - mid;
}
else {
cnt[2*node] = cnt[2*node+1] = 0;
}
lazy[2*node] = lazy[2*node+1] = lazy[node];
lazy[node] = {false,0};
}
if(st>r or en<l) return 0;
if(st>=l and en<=r) return cnt[node];
return query(l,r,st,mid,2*node) + query(l,r,mid+1,en,2*node+1);
}
void update(int l,int r,int val,int st,int en,int node) {
int mid = (st+en)/2;
if(st!=en and lazy[node].first) {
if(lazy[node].second) {
cnt[2*node] = mid - st + 1;
cnt[2*node+1] = en - mid;
}
else {
cnt[2*node] = cnt[2*node+1] = 0;
}
lazy[2*node] = lazy[2*node+1] = lazy[node];
lazy[node] = {false,0};
}
if(st>r or en<l) return;
if(st>=l and en<=r) {
cnt[node] = (en - st + 1)*val;
lazy[node] = {true,val};
return;
}
update(l,r,val,st,mid,2*node);
update(l,r,val,mid+1,en,2*node+1);
cnt[node] = cnt[2*node] + cnt[2*node+1];
}
};
void solve() {
int n;
cin>>n;
string s;
cin>>s;
vector<SegTree>tr(26,SegTree(n));
for(int i=0;i<n;i++) {
tr[s[i]-'a'].update(i,i,1,0,n-1,1);
}
int q;
cin>>q;
while(q--) {
int l,r;
cin>>l>>r;
vector<int>cnt(26);
for(int i=0;i<26;i++) {
cnt[i] = tr[i].query(l,r,0,n-1,1);
}
int odd = 0;
for(auto u:cnt) odd += u%2;
if(odd>1) continue;
for(int i=0;i<26;i++) {
tr[i].update(l,r,0,0,n-1,1);
}
int x = l,y = r;
for(int i=0;i<26;i++) {
if(cnt[i]/2) {
tr[i].update(x,x+cnt[i]/2-1,1,0,n-1,1);
tr[i].update(y-cnt[i]/2+1,y,1,0,n-1,1);
x += cnt[i]/2;
y -= cnt[i]/2;
cnt[i]%=2;
}
}
for(int i=0;i<26;i++) {
if(cnt[i]) {
tr[i].update(x,x,1,0,n-1,1);
}
}
}
string ans(n,'a');
for(int i=0;i<26;i++) {
for(int j=0;j<n;j++) {
if(tr[i].query(j,j,0,n-1,1)) {
ans[j] = (char)('a'+i);
}
}
}
cout<<ans<<enl;
}
signed main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);cout.tie(nullptr);
int testcases = 1;
cin>>testcases;
while(testcases--) solve();
return 0;
}

How to remove K characters from a string such that there is a minimum of each character

I want to remove K characters from a string such that the occurrence of each character is at a minimum.
For example:
String: abcdefghijkllllll
K: 5
Answer: 12 (abcdeghijkl)
String: ababac
K: 4
Answer: 3 (aac)
String: aaaab
K: 4
Answer: 1(b)
I want to remove 5 characters. Those characters would be 5 l's
What I've done so far is count the occurence of each character using a map
But I'm stuck as to what to do next.
#include <bits/stdc++.h>
using namespace std;
string s;
int l, k;
map<char, int> m;
int main() {
getline(cin, s);
scanf("%d %d", &l, &k);
for(int i=0; i<s.length(); i++) {
m[s[i]]++;
}
for(auto &x : m) {
cout << x.second << "\n";
}
return 0;
}
The expected result is the minimum length of a string after removing the characters of any given string (can be sorted or unsorted).
You can remove any character in the String
Update:
#include <bits/stdc++.h>
using namespace std;
string s;
int l, k;
map<char, int> m;
int main() {
getline(cin, s);
cin >> l >> k;
for(int i = 0; i < s.length(); i++) {
m[s[i]]++;
}
for(auto it = m.end(); it != m.begin(); it--) {
// cout << it->second << "\n";
}
vector<pair<int, int>> pairs;
for (auto itr = m.begin(); itr != m.end(); itr++) {
pairs.push_back(*itr);
}
sort(pairs.begin(), pairs.end(), [=](pair<int, int>& a, pair<int, int>& b) { return a.second < b.second; } );
for(auto it = m.end(); it != m.begin(); it--) {
if(it->second - k >= 1) {
it->second-=k;
k -= it->second;
}
}
int sum = 0;
for(auto it = m.end(); it != m.begin(); it--) {
sum += it->second;
// cout << it->second << "\n";
}
cout << sum << "\n";
return 0;
}
The current problem with this is that it doesn't read all the characters and map them correctly to the map.
I'm uncertain from your description and test cases what you're looking for. Your answer is returning the number of characters remaining in the string, and your updated function returns the sum variable. If that's the case why not just return the length of the string minus k?
Your second test case is:
String: ababac
K: 4
Answer: 3 (aac)
Removing 4 characters from "ababac" (length 6) would give it a length of 2, not 3. How does this work?
Can the characters be removed in any order? For the third test case you have:
String: aaaab
K: 4
Answer: 1(b)
Given the description: I want to remove K characters from a string such that the occurrence of each character is at a minimum. Removing 3 characters gives the result "ab". Removing the 4th could result in either "a" or "b". What do you do in this case?
There's a lot of ambiguity in this question, and the test cases are a bit confusing. For example, given "aabbccdddd" k=3, what would be the accepted answer? "abcdddd" or "aabbccd"? "abcdddd" would increase the number of characters that are at a minimum whereas "aabbccd" would reduce the number of the most frequently occurring character.
I've put together an answer using a max priority queue / max-heap (in Java) with the later example from above. This assumes that all your input is good.
import java.util.*;
public class SO {
//Helper class to put in the priority queue.
class CharInt {
char c;
int count;
public CharInt(char c) {
this.c = c;
this.count = 1;
}
void increment() {
this.count++;
}
void decrement() {
this.count--;
}
}
public int minChar(String s, int k) {
Map<Character, CharInt> map = new HashMap<Character, CharInt>();
for (Character c : s.toCharArray()) {
if (map.get(c) == null) {
map.put(c, new CharInt(c));
}else {
map.get(c).increment();
}
}
//Makes a Max-Heap from a PriorityQueue object. The comparator makes sure the top of the PriorityQueue is the character with the highest count.
PriorityQueue<CharInt> maxHeap = new PriorityQueue<CharInt>(new Comparator<CharInt>() {
#Override
public int compare(CharInt o1, CharInt o2) {
return - Integer.compare(o1.count, o2.count);
}
});
//Add all values to the heap.
for (CharInt c : map.values()) {
maxHeap.add(c);
}
//Take the top value off, decrement its count, add it back to the heap. Do this k times.
while (k-- > 0) {
CharInt c = maxHeap.poll();
c.decrement();
maxHeap.add(c);
}
StringBuilder builder = new StringBuilder(); // Used to make output string. Can be left out.
int sum = 0;
//Remove every element from the heap and get its count value.
while(!maxHeap.isEmpty()) {
CharInt c = maxHeap.poll();
for (int i = 0; i < c.count; i++) {
sum += c.count;
builder.append(c.c); // Used to make output string. Can be left out.
}
}
char[] chars = builder.toString().toCharArray(); // Used to make output string. Can be left out.
Arrays.sort(chars); // Used to make output string. Can be left out.
System.out.println(chars); // Used to make output string. Can be left out.
return sum;
}
public static void main(String...bannaa) {
int s = new SO().minChar("abcdefghijkllllll", 5);
int s2 = new SO().minChar("ababac", 4);
int s3 = new SO().minChar("aaaab", 4);
int s4 = new SO().minChar("abbbccc", 4);
System.out.println(s + " " + s2 + " " + s3 + " " + s4);
}
}
Output:
abcdefghijkl
ac
a
abc
12 2 1 3

Minimum number of swaps to convert a string to palindrome

We are given a string and we have to find out the minimum number of swaps to convert it into a palindrome.
Ex-
Given string: ntiin
Palindrome: nitin
Minimum number of swaps: 1
If it is not possible to convert it into a palindrome, return -1.
I am unable to think of any approach except brute force. We can check on the first and last characters, if they are equal, we check for the smaller substring, and then apply brute force on it. But this will be of a very high complexity, and I feel this question can be solved in another way. Maybe dynamic programming. How to approach it?
First you could check if the string can be converted to a palindrome.
Just have an array of letters (26 chars if all letters are latin lowercase), and count the number of each letter in the input string.
If string length is even, all letters counts should be even.
If string length is odd, all letters counts should be even except one.
This first pass in O(n) will already treat all -1 cases.
If the string length is odd, start by moving the element with odd count to the middle.
Then you can apply following procedure:
Build a weighted graph with the following logic for an input string S of length N:
For every element from index 0 to N/2-1:
- If symmetric element S[N-index-1] is same continue
- If different, create edge between the 2 characters (alphabetic order), or increment weight of an existing one
The idea is that when a weight is even you can do a 'good swap' by forming two pairs in one swap.
When weight is odd, you cannot place two pairs in one swap, your swaps need to form a cycle
1. For instance "a b a b"
One edge between a,b of weight 2:
a - b (2)
Return 1
2. For instance: "a b c b a c"
a - c (1)
b - a (1)
c - b (1)
See the cycle: a - b, b - c, c - a
After a swap of a,c you get:
a - a (1)
b - c (1)
c - b (1)
Which is after ignoring first one and merge 2 & 3:
c - b (2)
Which is even, you get to the result in one swap
Return 2
3. For instance: "a b c a b c"
a - c (2)
One swap and you are good
So basically after your graph is generated, add to the result the weight/2 (integer division e.g. 7/3 = 3) of each edge
Plus find the cycles and add to the result length-1 of each cycle
there is the same question as asked!
https://www.codechef.com/problems/ENCD12
I got ac for this solution
https://www.ideone.com/8wF9DT
//minimum adjacent swaps to make a string to its palindrome
#include<bits/stdc++.h>
using namespace std;
bool check(string s)
{
int n=s.length();
map<char,int> m;
for(auto i:s)
{
m[i]++;
}
int cnt=0;
for(auto i=m.begin();i!=m.end();i++)
{
if(i->second%2)
{
cnt++;
}
}
if(n%2&&cnt==1){return true;}
if(!(n%2)&&cnt==0){return true;}
return false;
}
int main()
{
string a;
while(cin>>a)
{
if(a[0]=='0')
{
break;
}
string s;s=a;
int n=s.length();
//first check if
int cnt=0;
bool ini=false;
if(n%2){ini=true;}
if(check(s))
{
for(int i=0;i<n/2;i++)
{
bool fl=false;
int j=0;
for(j=n-1-i;j>i;j--)
{
if(s[j]==s[i])
{
fl=true;
for(int k=j;k<n-1-i;k++)
{
swap(s[k],s[k+1]);
cnt++;
// cout<<cnt<<endl<<flush;
}
// cout<<" "<<i<<" "<<cnt<<endl<<flush;
break;
}
}
if(!fl&&ini)
{
for(int k=i;k<n/2;k++)
{
swap(s[k],s[k+1]);
cnt++;
}
// cout<<cnt<<" "<<i<<" "<<endl<<flush;
}
}
cout<<cnt<<endl;
}
else{
cout<<"Impossible"<<endl;
}
}
}
Hope it helps!
Technique behind my code is Greedy
first check if palindrome string can exist for the the string and if it can
there would be two cases one is when the string length would be odd then only count of one char has be odd
and if even then no count should be odd
then
from index 0 to n/2-1 do the following
fix this character and search for this char from n-i-1 to i+1
if found then swap from that position (lets say j) to its new position n-i-1
if the string length is odd then every time you encounter a char with no other occurence shift it to n/2th position..
My solution revolves around the palindrome property that first element and last element should match and if their adjacent elements also do not match then its not a palindrome. Keep comparing and swapping till both reach the same element or adjacent elements.
Written solution in java as below:
public static void main(String args[]){
String input = "natinat";
char[] arr = input.toCharArray();
int swap = 0;
int i = 0;
int j = arr.length-1;
char temp;
while(i<j){
if(arr[i] != arr[j]){
if(arr[i+1] == arr[j]){
//swap i and i+1 and increment i, decrement j, swap++
temp = arr[i];
arr[i] = arr[i+1];
arr[i+1] = temp;
i++;j--;
swap++;
} else if(arr[i] == arr[j-1]){
//swap j and j-1 and increment i, decrement j, swap++
temp = arr[j];
arr[j] = arr[j-1];
arr[j-1] = temp;
i++;j--;
swap++;
} else if(arr[i+1] == arr[j-1] && i+1 != j-1){
//swap i and i+1, swap j and j-1 and increment i, decrement j, swap+2
temp = arr[j];
arr[j] = arr[j-1];
arr[j-1] = temp;
temp = arr[i];
arr[i] = arr[i+1];
arr[i+1] = temp;
i++;j--;
swap = swap+2;
}else{
swap = -1;break;
}
} else{
//increment i, decrement j
i++;j--;
}
}
System.out.println("No Of Swaps: "+swap);
}
My solution in java for any type of string i.e Binary String, Numbers
public int countSwapInPalindrome(String s){
int length = s.length();
if (length == 0 || length == 1) return -1;
char[] str = s.toCharArray();
int start = 0, end = length - 1;
int count = 0;
while (start < end) {
if (str[start] != str[end]){
boolean isSwapped = false;
for (int i = start + 1; i < end; i++){
if (str[start] == str[i]){
char temp = str[i];
str[i] = str[end];
str[end] = temp;
count++;
isSwapped = true;
break;
}else if (str[end] == str[i]){
char temp = str[i];
str[i] = str[start];
str[start] = temp;
count++;
isSwapped = true;
break;
}
}
if (!isSwapped) return -1;
}
start++;
end--;
}
return (s.equals(String.valueOf(str))) ? -1 : count;
}
I hope it helps
string s;
cin>>s;
int n = s.size(),odd=0;
vi cnt(26,0);
unordered_map<int,set<int>>mp;
for(int i=0;i<n;i++){
cnt[s[i]-'a']++;
mp[s[i]-'a'].insert(i);
}
for(int i=0;i<26;i++){
if(cnt[i]&1) odd++;
}
int ans=0;
if((n&1 && odd == 1)|| ((n&1) == 0 && odd == 0)){
int left=0,right=n-1;
while(left < right){
if(s[left] == s[right]){
cnt[left]--;
cnt[right]--;
mp[s[left]-'a'].erase(left);
mp[s[right]-'a'].erase(right);
left++;
right--;
}else{
if(cnt[left]&1 == 0){
ans++;
int index = *mp[s[left]-'a'].rbegin();
mp[s[left]-'a'].erase(index);
mp[s[right]-'a'].erase(right);
mp[s[right]-'a'].insert(index);
swap(s[right],s[index]);
cnt[left]-=2;
}else{
ans++;
int index = *mp[s[right]-'a'].begin();
mp[s[right]-'a'].erase(index);
mp[s[left]-'a'].erase(left);
mp[s[left]-'a'].insert(index);
swap(s[left],s[index]);
cnt[right]-=2;
}
left++;
right--;
}
}
}else{
// cout<<odd<<" ";
cout<<"-1\n";
return;
}
cout<<ans<<"\n";

NxN matrix is given and we have to find

N things to select for N people, you were given a NxN matrix and cost at each element, you needed to find the one combination with max total weight, such that each person gets exactly one thing.
I found difficulty in making its dp state.
please help me and if possible then also write code for it
C++ style code:
double max_rec(int n, int r, int* c, double** m, bool* f)
{
if (r < n)
{
double max_v = 0.0;
int max_i = -1;
for (int i = 0; i < n; i++)
{
if (f[i] == false)
{
f[i] = true;
double value = m[r][i] + max_rec(n, r + 1, c, m, f);
if (value > max_v)
{
max_v = value;
max_i = i;
}
f[i] = false;
}
}
c[i] = max_i;
return max_v;
}
return 0.0;
}
int* max_comb(int n, double** m)
{
bool* f = new bool[n];
int* c = new int[n];
max_rec(n, 0, c, m, f);
delete [] f;
return c;
}
Call max_comb with N and your NxN matrix (2d array). Returns the column indices of the maximum combination.
Time complexity: O(N!)
I know this is bad but the problem does not have a greedy structure.
And as #mszalbach said, try to attempt the problem yourself before asking.
EDIT: can reduce to polynomial time by memoizing.

Recursive Merge Sort C++

I want to write a recursive merge sort program in C++. The problem is, I don't know how to get the base case idea working recursively. Can anybody please tell me what would be the base case for Merg Function(), Split Function() and MergSort() function. I would be thankful to you.
void Merg(int A[], int s1, int e1, int s2, int e2)
{
int B[8];
int i=0;
while (A[s1] < A[s2])
B[i] = B[s1];
i++;
s1++;
if (s1 == e1)
{
B[i] = A[s2];
i++;
s2++;
}
while (A[s2] < A[s1])
B[i] = B[s2];
i++;
s2++;
if (s2 == e2)
{
B[i] = A[s1];
i++;
s1++;
}
}
void Split(int A[], int s, int e)
{
int mid = (s+e)/2;
if (s < e && mid != 0)
{
Split(A, s, mid);
Split(A, mid+1, e);
}
Merg(A, s, mid, mid+1, e);
}
int main()
{
int A[8] = {10,4,8,12,11,2,7,5};
Split(A, 0, 7);
return 0;
}
The base case is an array that is guaranteed to be sorted, so either an empty array or an array of length 1.
Your merge function is not correct, but at least contains most of the right ideas. All you need there is a further wrapping loop and a few conditions to prevent your merge running past the end of the arrays. The split function is totally off, splitting is not recursive, further splits happen inside the recursive mergeSort calls.
if length(A) < 2 return // already sorted
split A in lower half L and upper half H
merge-sort L
merge-sort H
merge the sorted L and H
done

Resources