My code does not work in some cases: when c1 is 4, it doesn't output anything, but it works for numbers greater than 9. Why is that?
#include<iostream>
#include<vector>
using namespace std;
void insertfast(vector<int>&v, int c)
{
if (c >= v[v.size()-1])v.push_back(c);
if (c <= v[0])v.insert(v.begin(), c);
int min = 1;
int max = v.size();
while (v.size() != 9) {
int i = (min + max) / 2;
if (v[i - 1] <= c && c <= v[i])v.insert(v.begin() + i, c);
if (v[i] <= c && c <= v[i + 1])v.insert(v.begin() + (i + 1), c);
if (c < v[i])
max = i;
else
min = i;
}
}
int main()
{
vector<int>v1 = { 2,5,9,22,44,55,88,777 };
int c1 = 4;
insertfast(v1, c1);
for (int i = 0; i < 9; i++)
cout << v1[i] << endl;
}
Let's just take a second to logically step through the code here, since I assume this is a homework question, it's important to understand how to do this. There are tools like debuggers that are used on larger projects and more difficult problems, but small logic errors like this happen all the time.
Ok, so insertfast() is a function to insert an int into a vector<int> in an ordered manner. The first thing you do is compare against the first and last elements of the vector.
if (c >= v[v.size() - 1])
v.push_back(c);
if (c <= v[0])
v.insert(v.begin(), c);
We can only be one of these things, and if either are true we are done. So the best option here is to just return from the function, we don't care about doing anything else. We know that, but the program doesn't. It'll keep on comparing things we don't want to compare and bug out.
if (c >= v[v.size() - 1]) {
v.push_back(c);
return;
}
if (c <= v[0]) {
v.insert(v.begin(), c);
return;
}
What if both of these statements are false, and we are still in the function? We still need to figure where to insert this value, so we loop through the elements.
while (v.size() != 9)
This is a very poor conditional loop, since it will only work if we pass a vector of size 8 into the function. With your particular arithmetic, you essentially want to loop until some value is added to the vector. I recommend an unconditional loop (we are trying to be "fast" after all) aka an infinite loop, and explicitly return or break within the loop.
int min = 1;
int max = v.size();
while (1) {
int i = (min + max) / 2;
if (v[i - 1] <= c && c <= v[i]) {
v.insert(v.begin() + i, c);
return;
}
if (v[i] <= c && c <= v[i + 1]) {
v.insert(v.begin() + (i + 1), c);
return;
}
if (c < v[i])
max = i;
else
min = i;
}
break instead of return will also work just fine here, since if you break out of this loop, the end of the function is hit and you just return anyways. So, we solved the problem just by rethinking the design and stepping through the code.
You have two logic problems in your code:
For your test data in insertfast() function you step into while(), when you step into first if (v[i - 1] <= c && c <= v[i]) you insert 4 value and in becomes v[1], and you have step right after that into next if (v[i] <= c && c <= v[i + 1]), so you need to set second if as else if, like this:
if (v[i - 1] <= c && c <= v[i])
{
v.insert(v.begin() + i, c);
}
else if (v[i] <= c && c <= v[i + 1])
{
v.insert(v.begin() + (i + 1), c);
}
From the previous item your vector increased for 2 elements, so his size becomes 10, and you had infinite loop while (v.size() != 9), I think you can just do break to leave loop in case of success insert:
if (v[i - 1] <= c && c <= v[i])
{
v.insert(v.begin() + i, c);
break;
}
else if (v[i] <= c && c <= v[i + 1])
{
v.insert(v.begin() + (i + 1), c);
break;
}
There is no need to run loop further, if you have inserted element.
Actually 2nd item with break will fix and else missing problem, in case of insertion it will leave loop and won't be able to step into second if.
This is the Triangle problem from Codility:
A zero-indexed array A consisting of N integers is given.
A triplet (P, Q, R) is triangular if 0 β€ P < Q < R < N and:
A[P] + A[Q] > A[R],
A[Q] + A[R] > A[P],
A[R] + A[P] > A[Q].
Write a function:
int solution(vector<int> &A);
that, given a zero-indexed array A consisting of N integers, returns 1
if there exists a triangular triplet for this array and returns 0
otherwise.
For example, given array A such that:
A[0] = 10, A[1] = 2, A[2] = 5, A[3] = 1, A[4] = 8, A[5] = 20
Triplet (0, 2, 4) is triangular, the function should return 1.
Given array A such that:
A[0] = 10, A[1] = 50, A[2] = 5, A[3] = 1
function should return 0.
Assume that:
N is an integer within the range [0..100,000];
each element of array A is an integer within the range
[β2,147,483,648..2,147,483,647].
And here is my solution in C++:
int solution(vector<int> &A) {
if(A.size()<3) return 0;
sort(A.begin(), A.end());
for(int i=0; i<A.size()-2; i++){
//if(A[i] = A[i+1] = A[i+2]) return 1;
if(A[i]+A[i+1]>A[i+2] && A[i+1]+A[i+2]>A[i] && A[i+2]+A[i]>A[i+1]){
return 1;
}
}
return 0;
}
I've checked the comments there and all the solutions seems similar to mine.
However, while others claimed to have gotten 100%, I only got a 93% score.
I got all the tests cases correct EXCEPT for one:
extreme_arith_overflow1
overflow test, 3 MAXINTs
I assume this case has some input like this:
[2147483647, 2147483647, 2147483647]
So I add this to the custom test case, and the answer turns out to be 0 when it clearly should be 1.
I also tried [1900000000, 1900000000, 1900000000], and the answer is still 0.
However, [1000000000, 1000000000, 1000000000] is correct with answer of 1.
Can anyone clue me in on why this result occured?
Greatly appreciated.
My solution in Java with 100/100 and time complexity of O(N*log(N))
With comments explaining the logic
// you can also use imports, for example:
// import java.util.*;
// you can write to stdout for debugging purposes, e.g.
// System.out.println("this is a debug message");
import java.util.Arrays;
class Solution {
public int solution(int[] A) {
int N = A.length;
if (N < 3) return 0;
Arrays.sort(A);
for (int i = 0; i < N - 2; i++) {
/**
* Since the array is sorted A[i + 2] is always greater or equal to previous values
* So A[i + 2] + A[i] > A[i + 1] ALWAYS
* As well ass A[i + 2] + A[i + 1] > A[i] ALWAYS
* Therefore no need to check those. We only need to check if A[i] + A[i + 1] > A[i + 2]?
* Since in case of A[i] + A[i + 1] > MAXINT the code would strike an overflow (ie the result will be greater than allowed integer limit)
* We'll modify the formula to an equivalent A[i] > A[i + 2] - A[i + 1]
* And inspect it there
*/
if (A[i] >= 0 && A[i] > A[i + 2] - A[i + 1]) {
return 1;
}
}
return 0;
}
Basically when you check X + Y value of integers, that is greater than integer limit the code will fail on overflow. so instead of checking if X + Y > Z, we can simply check the equivalent statement if X > Z - Y (simple math isn't it?). Alternatively you could always use long but it will be a worse solution memory wise.
Also make sure you skip the negatives as a triangle cannot have a negative side value.
Cheers
Java 100 %:
public int solution(int[] A){
Arrays.sort(A);
for(int i=0;i<A.length-2;i++){
if(
((long)A[i] + (long)A[i+1] > A[i+2]) &&
((long)A[i+1] + (long)A[i+2] > A[i]) &&
((long)A[i] + (long)A[i+2] > A[i+1])
)
return 1;
}
return 0;
}
Here's my clean solution in Python. I got a 100% in Codility.
This logic can be adapted to any other programming language.
Note: If the array is sorted, you only have to check that the sum of two consecutive elements is greater than the next element (A[i] + A[i+1] > A[i+2]), because in that case, the other two conditions (A[i+1]+A[i+2] > A[i], A[i]+A[i+2] > A[i+1]) will always be true.
I hope it helps.
def solution(A):
#edge case check
if len(A) < 3:
return 0
A.sort()
for i in range(len(A)-2):
if A[i]+A[i+1] > A[i+2]:
return 1
return 0
There are couple of issues here
Side of a triangle can't be 0, since it is a length. You have to add that check or you'll fail that corner case. i.e. Wouldn't get 100%.
Since you can have an input array of all INT_MAX or LONG_MAX (see http://www.cplusplus.com/reference/climits/), you need to store the sum in a double or long long.
You don't have to check all three conditions here i.e.
A[P] + A[Q] > A[R],
A[Q] + A[R] > A[P],
A[R] + A[P] > A[Q].
If you have sorted the array than
A[Q] + A[R] > A[P] &&
A[R] + A[P] > A[Q]
are always true because 0 β€ P < Q < R i.e. R is greater than P and Q.
So you should only check for A[P] + A[Q] > A[R].
You have already placed a check for A.size() < 3 so that is good.
I have added a C implementation at https://github.com/naveedrasheed/Codility-Solutions/blob/master/Lesson6_Sorting/triangle.c.
You can compare it with solution.
I have used 3 for loop here( without sorting the array) to solve this problem.
public static int solution(int[] A) {
for (int p = 0; p < A.length; p++) {
for (int q = p + 1; q < A.length; q++) {
for (int r = q + 1; r < A.length; r++) {
if ((A[p] + A[q] > A[r]) && (A[q] + A[r] > A[p]) && (A[r] + A[p] > A[q])) {
System.out.println(A[p] + " " + A[q] + " " + A[r]);
return 1;
}
}
}
}
return 0;
}
the trick is to find a number on the array that is less the sum of the other two on the array so sorting the array then searching for that number will solve it. casting to long that on sometimes the value of summation wil exceed the allowed integer
public int solution(int[] A) {
int n = A.length;
if(n<3){
return 0;
}
Arrays.sort(A);
for(int i=2; i<n; i++){
if(A[i]<(long)A[i-1]+(long)A[i-2])
return 1;
}
return 0;
}
My solution in C# with 100 score.
using System;
class Solution {
public int solution(int[] A) {
// write your code in C# 6.0 with .NET 4.5 (Mono)
if(A.Length) <3)
return 0;
Array.Sort(A);
int p,q,r;
for(int i=A.Length-1;i>1; i--){
p = A[i];
q = A[i-1];
r = A[i-2];
if(p+q>r && q+r > p && r+p > q)
return 1;
}
return 0;
}
}
Straightforward solution in JavaScript.
Note: I excluded the options where any side could be 0 or less. The rest is the same.
function solution(A) {
if (A.length < 3) return 0;
A.sort((a, b) => (a - b));
for (i = A.length - 1; i >= 0; i--) {
if (A[i - 2] <= 0) return 0;
if (
A[i] + A[i - 1] > A[i - 2] &&
A[i] + A[i - 2] > A[i - 1] &&
A[i - 1] + A[i - 2] > A[i]
) return 1;
}
return 0;
}
javascript 100% on codility
function solution(a) {
if (a.length < 3) {
return 0;
}
a.sort((a, b) => a - b);
for (let i = 0; i < a.length - 2; i++) {
if (a[i] + a[i + 1] > a[i + 2]) {
return 1;
}
}
return 0;
}
My solution to this problem, written in Swift.
public func Triangle(_ A : inout [Int]) -> Int {
A.sort()
for i in 1..<A.count-1 {
if(A[i] + A[i-1] > A[i+1]) {
print("Triangle has edges: \(A[i-1]), \(A[i]), \(A[i+1])")
return 1
}
}
return 0
}
A = [10,2,5,1,8,20]
print("Triangle: ", Triangle(&A))
Or you can change the if clause, like below
if(A[i]>A[i+2]-A[i+1] && A[i+1]>A[i]-A[i+2] && A[i+2]>A[i+1]-A[i])
using subtraction instead of addition.
Works 100%, tested with different scenario's.
I think all the possibilities are not covered above solution
Combination with
P,Q,R
A[0] = 10, A[1] = 2, A[2] = 5, A[3] = 1, A[4] = 8, A[5] = 20
index combination
0+1>2, 1+2>0, 2+0>1
1+2>3, 2+3>1, 3+1>2
....
These are combinations needed to achieve this problem.
//Triangle
/**
* A[P] + A[Q] > A[R],
A[Q] + A[R] > A[P],
A[R] + A[P] > A[Q]
*/
public int triangleSolution(int[] A) {
int status = 0;
for(int i=0; i<A.length; i++) {
int[] B = removeTheElement(A, i);
for(int j=0; j<B.length; j++) {
int[] C = removeTheElement(B, j);
for(int k=0; k<C.length; k++) {
if((A[i] + B[j] > C[k]) &&
(B[j] + C[k] > A[i]) &&
(C[k] + A[i] > B[j])) {
return 1;
}
}
}
}
return status;
}
// Function to remove the element
public int[] removeTheElement(int[] arr, int index)
{
// Create another array of size one less
int[] anotherArray = new int[arr.length - 1];
// Copy the elements except the index
// from original array to the other array
for (int i = 0, k = 0; i < arr.length; i++) {
// if the index is
// the removal element index
if (i == index) {
continue;
}
// if the index is not
// the removal element index
anotherArray[k++] = arr[i];
}
//Java >8
//IntStream.range(0, arr.length).filter(i -> i != index).map(i -> arr[i]).toArray();
return anotherArray;
}
//My solution in C++ it avoid overflow
inline int Triangle(vector<int> &A) {
if(A.size() < 3) return 0;
sort(A.begin(), A.end());
for(int i = 0; i < (int)A.size() - 2; ++i){
int P = A[i], Q = A[i + 1], R =A[i + 2];
if(( R - P - Q < 0) && ( P - Q - R < 0) && (Q - R - P < 0))
return 1;
}
return 0;
}
Ruby 100% solution
def solution(a)
arr = a.select{|x| x >=0 }.sort
arr.each_with_index do |p, pi|
arr[(pi+1)..-1].each_with_index do |q, qi|
arr[(qi+pi+2)..-1].each do |r|
break if p+q <=r
break if p+r <=q
break if r+q <=p
return 1
end
end
end
0
end
It's javascript solution(TC: O(N*log(N)) though, in case you guys want :).
function solution(A) {
if(A.length<3) return 0;
A.sort((a,b)=>b - a);
for(let i = 0,j = i+1;j < A.length-1;j++){
let p = A[j],q = A[j+1],r = A[i]
if(r - p > q) i++;
else if(r - p < q) return 1;
}
return 0;
}
Sorting does not work now, It was a bug it was fixed by Codility. Now, I am using this piece of code to get 93%
You can see the results below:
Codility test Results
0 <= P < Q < R < N
public static int solution(int[] unfilteredArray) {
int[] array = filterLessThanOneElements(unfilteredArray);
for(int i = 0; i <= (array.length - 3) ; i++) {
long p = array[i];
for(int j = i+1; j <= (array.length - 2); j++) {
long q = array[j];
for(int k = j+1; k <= (array.length - 1); k++) {
long r = array[k];
if((p + q > r) && (q + r > p) && (r + p > q)) {
return 1;
}
}
}
}
return 0;
}
// The mose efficient way to remove duplicates
// TIME COMPLEXITY : O(N)
private static int[] filterLessThanOneElements(int[] unfilteredArray) {
int k = 0;
for(int i = 0; i < unfilteredArray.length; i++) {
if(unfilteredArray[i] > 0) {
unfilteredArray[k++] = unfilteredArray[i];
}
}
return Arrays.copyOfRange(unfilteredArray, 0, k);
}
Simple change: First, you observe that negative integers cannot be part of a triangular triplet. That means you can cast all ints to unsigned int, and there canβt be any overflow anymore.
100/100 JavaScript solution
function solution(A) {
let l = A.length;
if (l < 3) {
return 0;
}
A.sort((a, b) => a - b);
for (let i = 0; i < l - 2; i++) {
let [p, q, r] = [A[i], A[i + 1], A[i + 2]];
if (p + q > r && q + r > p && r + p > q) {
return 1;
}
}
return 0;
}
If you don't want to use Array.sort, the following works with 100% correctness and 100% performance with a complexity that codility detects at O(N*log(N)).
class Solution {
public int solution(int[] A) {
int ans = 0;
int p1 = -1;
int p2 = -1;
int p1Pos = 0;
int p2Pos = 1;
int cur = -1;
if(A.length > 2){
p1 = A[0];
p2 = A[1];
for(int i = p2Pos + 1; i < A.length; i++){
if(p1 > p2){
p2 = A[p1Pos];
p1 = A[p2Pos];
A[p2Pos] = p2;
A[p1Pos] = p1;
}
cur = A[i];
//System.out.println(p1 + " " + p2 + " " + cur);
if(p1 > -1 && p2 > -1){
//the test for a triangle
if (cur > -1 &&
((p1 == p2 && p2 == cur) ||
((p1 + p2 > cur) && (p1 + cur > p2) && ( cur + p2 > p1)))){
return 1;
//bubble sort...sort of
}else if (p2 > cur){
A[p2Pos] = cur;
A[i] = p2;
if(p1 < cur){
p1 = cur;
p1Pos = p2Pos;
}
p2Pos = i;
} else if(cur > -1
&&(p1 + p2 <= cur) ){
p2Pos++;
p1Pos++;
p1=p2;
p2=cur;
}
}else{
//find the first two positive numbers
if((p2 < 0 || p1 < 0) && cur > -1){
if(p1 < 0){
p1 = cur;
p1Pos = i;
}else{
p2 = A[i];
p2Pos = i;
}
}
}
}
}
return ans;
}
}
When I was making this I thought that maybe I could solve this while doing a modified Bubble sort. I chose two pivots (p1 and p2), while making sure p2 > p1.
As I iterated through the array, I made sure that p2 would bubble up if p2 > cur and that p1 would additionally bubble up if p1 > cur. I Furthermore, I noticed that any combination of three points that have a negative number cannot be a triangle. So I ignored negatives. I also realized that if the array happened to hold three and only maximal integers that I would have an issue. To solve this I tested for p1 == p2 == cur. Admittingly, it might be better to use BigInteger to solve it.
My 100% JavaScript solution with O(N*log(N)) time complexity:
function solution(A) {
A.sort((a, b) => a - b);
for (let i = 0, len = A.length - 2; i < len; i++) {
const [P, Q, R] = [A[i], A[i + 1], A[i + 2]];
if (P + Q > R && Q + R > P && R + P > Q) {
return 1;
}
}
return 0;
}
One would think that sorting the array first will violate the condition 0<=P<Q<R. But the question is does such a triple exist. For the example we find [10,2,5,1,8,20]. After sorting we still find the values 10, 5, and 8 as the triple, but in a different order.
A Python 3 solution with 100% score at Codility:
def triangle(A):
n = len(A)
if n < 3:
return 0
a = list(A)
if 0 not in a:
a.append(0)
a.sort()
#print(a)
n = len(a)
p_a = a[a.index(0)+1:n]
#print(p_a)
n = len(p_a)
for i in range(n-2):
p = p_a[i]
q = p_a[i+1]
r = p_a[i+2]
if (p+q>r):
return (1)
return 0
Better solutions for C++ is to change a little algorithm. Make subtraction instead of adding, here is an example:
int solution(vector<int> &A) {
if (A.size() < 3)
return 0;
sort(A.begin(), A.end());
for (int i = 0; i < A.size() - 2; i++) {
if (A[i] > 0 && (A[i] > A[i + 2] - A[i + 1]))
return 1;
}
return 0;
}
It's because of integer overflow.
Try out this one:
int a1 = 1900000000;
int a2 = 1900000000;
int sum = a1+a2; // sum will be -494967296
Edit: Use long long int.
long long int sum01 = A[i] + A[i+1];
long long int sum12 = A[i+1] + A[i+2];
long lont int sum02 = A[i] + A[i+2];
if (sum01 > A[i+2] && sum12 > A[i] && sum02 > A[i+1])
return 1;
My java Solution 100/100 Instead of comparing the Addition we compare the subtraction as we can have an Integer.MAX_VALUE an we will be getting corrupted data.
public static int solution(int[] A) {
int isATriangle = 0;
Arrays.sort(A);
if (A.length >= 3) {
for (int i = 0; i < A.length - 2; i++) {
if (A[i] > A[i + 2] - A[i + 1]
&& A[i + 2] > A[i] - A[i + 1]
&& A[i + 2] > A[i + 1] - A[i])
isATriangle = 1;
}
}
return isATriangle;
}