Related
I currently acheive shuffle one of array without duplicated with previous value of next value.
However, I don't think my method is good. I think there are better way.
Firstly, I will describe what the array looks like.
it's an array of object with property {answer,url,category} and there are duplicated item in the array. think as [A,A,B,B,C,C] , A,B,C as object here.
As EzioMerce pointed out, in this array, object will always has equal amount of numbers. such if there are 3 A, will definitely have 3 B and C. It will not have array as such [A,A,A,B]
I need the array to shuffle until there is no consecutive object next to each other such as [A,B,C,B,A,C]
Here is my solution (which I have tested 40 times without consecutive object):
getShuffleWords(array: Card[]) {
//First shuffle..
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor( Math.random() * (i - 1));
if (j > 0) {
//make sure there are no simliar value around position i and j
if (array[i]?.answer !== array[j - 1]?.answer
&& array[i]?.answer !== array[j + 1]?.answer
&& array[i]?.answer !== array[j - 1]?.answer
&& array[i]?.answer !== array[j + 1]?.answer) {
[array[i], array[j]] = [array[j], array[i]];
}
} else {
if (array[i]?.answer !== array[j + 1]?.answer) {
[array[i], array[j]] = [array[j], array[i]];
}
}
}
const before = [...array];
console.log(before);
//Checking duplicate and swap with other value
for (let x = 0; x < array.length; x++){
if (array[x].answer == array[x + 1]?.answer) {
console.log(x,array[x])
for (let y = 0; y < array.length; y++){
//make sure there are no simliar value around position x and y
if (array[y]?.answer !== array[x]?.answer
&& array[y + 1]?.answer !== array[x].answer
&& array[y - 1]?.answer !== array[x].answer
&& array[y]?.answer !== array[x+1]?.answer
&& array[y]?.answer !== array[x-1]?.answer
) {
console.log(y, array[y]);
if (x < y) {
[array[x], array[y]] = [array[y], array[x]];
} else {
[array[y], array[x]] = [array[x], array[y]];
}
break;
}
}
}
}
//just another caculate if there is duplication left (for testing purpose)
let dup = 0;
for (let x = 0; x < array.length; x++){
if (array[x].answer == array[x + 1]?.answer) {
dup++;
}
}
console.log(array, dup);
return array;
}
However, in the //First shuffle.. there are always has some consecutive object exisited in the array. thats why I repeat another checking and replace the value.
How would I improve my method. and why my first shuffle does not work perfectly?
You can try this way. It also works if arr will be an array of objects
const arr = [1, 2, 3, 1, 2, 3, 1, 2, 3];
const shuffle = (arr) => {
const uniqueArr = [...(new Set(arr))];
const shuffledArr = [];
let countOfOneObj = 0;
for (const obj of arr) {
if (obj === arr[0]) ++countOfOneObj;
};
const getRandomObj = () => {
const i = Math.floor(Math.random() * uniqueArr.length);
return uniqueArr[i];
}
for (let i = 0; i < countOfOneObj; ++i) {
let usedObjs = []
for (let j = 0; j < uniqueArr.length; ++j) {
const obj = getRandomObj();
if (
usedObjs.includes(obj) ||
shuffledArr[shuffledArr.length - 1] === obj
) {
--j;
continue;
}
usedObjs.push(obj);
shuffledArr.push(obj);
}
usedObjs = [];
}
return shuffledArr;
}
console.log(shuffle(arr));
You could shuffle an array of indices of same grouped values until you got a result which has no same neighbour indices.
const
fy = array => { // fisher-yates, adapted from https://stackoverflow.com/a/59837259/1447675
let i = array.length;
while (--i) {
const j = Math.floor(Math.random() * (i + 1));
[array[j], array[i]] = [array[i], array[j]];
}
},
shuffle = array => {
do fy(array);
while (array.some((v, i, a) => v === a[i + 1]))
};
indices = [0, 0, 0, 1, 1, 1, 2, 2];
shuffle(indices);
console.log(...indices);
Recently doing leetcode but encounter difficulties in this 4 sum question. For the kSum function below, I saw some of the solutions online, passing an empty array as a parameter to store the result. I think it makes kSum() too many parameters.
I am thinking of refactoring kSum() holds a parameter of itself but not much process. It return something strange(eg. an empty array)
I would like to ask what I am missing to make my algorithm works? I think the problem may due to the second for loop which loop through kSum(nums, i+1, ...) ?
const fourSum = (nums, target) => {
const sortedNumsArray = nums.sort((a, b) => a - b)
return kSum(sortedNumsArray, 0, 4, target)
}
const kSum = (nums, start, k, target) => {
const result = [];
if( nums.length === start || nums[nums.length - 1] * k < target || nums[start] * k > target) return result;
if (k === 2) {
return twoSum(nums, 0, target)
} else {
let shouldCheck = false;
for (let i = start; i < nums.length; i++) {
if (shouldCheck && nums[i] !== nums[i - 1]) {
for (let set of kSum(nums, i + 1, k - 1, target - nums[i])) {
result.push([nums[i]])
result[result.length - 1].concat(set)
}
}
shouldCheck = true;
}
}
return result;
}
const twoSum = (nums, start, target) => {
let left = start;
let right = nums.length - 1
let subResult = []
while (left < right) {
let sum = nums[left] + nums[right]
if (sum === target) {
subResult.push([nums[left++], nums[right--]])
while (left < right && nums[left] === nums[left + 1]) { left++ }
while (left < right && nums[right] === nums[right - 1]) { right-- }
} else if (sum > target) {
right--
} else {
left++
}
}
return subResult;
}
function insertDash(str) {
var arr = str.split("");
for (var i = 0; i < arr.length; i++) {
if (arr[i] % 2 != 0 && arr[i + 1] % 2 != 0) {
var x = arr.splice(i + 1, 0, '-');
}
}
return arr;
}
console.log(insertDash("99999"));
You can use a String#replace with a regular expression with a lookahead:
function insertDash(string) {
return string.replace(/([13579](?=[13579]))/g, "$1-");
}
console.log(insertDash("99999"));
console.log(insertDash("1122334455"));
The other option is to use Array#reduce to create the string:
function insertDash(string) {
return string.split('').reduce(function(s, c, i, arr) {
return s + c + (c % 2 && arr[i + 1] % 2 ? '-' : '');
}, '');
}
console.log(insertDash("99999"));
console.log(insertDash("1122334455"));
You could iterate from the end of the array, because you probably insert a dash and the array gets a new length.
If you start at the end, you change not the length of the items which are eligible to test and for inserting a dash.
function insertDash(string) {
var array = string.split(""),
i = array.length;
while (i--) {
if (array[i] % 2 && array[i + 1] % 2) {
array.splice(i + 1, 0, '-');
}
}
return array.join('');
}
console.log(insertDash("99999"));
console.log(insertDash("1122334455"));
Given a sequence of integers as an array,i have to determine whether it is possible to obtain a strictly increasing sequence by removing no more than one element from the array. Example
For sequence = [1, 3, 2, 1], the output should be
almostIncreasingSequence(sequence) = false
There is no one element in this array that can be removed in order to get a strictly increasing sequence.
For sequence = [1, 3, 2] the output should be
almostIncreasingSequence(sequence) = true
We can remove 3 from the array to get the strictly increasing sequence [1, 2]. Alternately, we can remove 2 to get the strictly increasing sequence [1, 3].
The function must return true if it is possible to remove one element from the array in order to get a strictly increasing sequence, otherwise return false.
Here is what i have already tried , but it doesnt work for all situations
function almostIncreasingSequence(sequence) {
for (var i = 0; i < sequence.length; i++) {
if (sequence[i] > sequence[i + 1]) {
sequence.splice(i, 1);
return true;
};
return false;
};
}
function almostIncreasingSequence(sequence) {
var found = false;
for (var i=0;i<sequence.length;i++) {
if(sequence[i] <= sequence[i-1]) {
if(found) {
return false;
}
found = true;
if(i === 1 || i + 1 === sequence.length) {
continue;
}
else if (sequence[i] > sequence[i-2]) {
sequence[i-1] = sequence[i-2];
}
else if(sequence[i-1] >= sequence[i+1]) {
return false;
}
}
}
return true;
}
Here is my solution.
First I look for a decreasing sequence. If none, then return true
If there is a decreasing sequence inside the array, I create two more arrays excluding the two items in the decreasing sequence, and check those two new arrays. If one of them has no decreasing sequences, then return true, otherwise return false
function indexOfFail(sequence) {
let index = null;
for (let i = 0; i < sequence.length -1; i++) {
if (sequence[i] >= sequence[i + 1]) {
index = i;
break;
}
}
return index;
}
function almostIncreasingSequence(sequence) {
let index = indexOfFail(sequence);
if (index == null) return true;
let tmp1 = sequence.slice(0);
tmp1.splice(index, 1); //remove failed item
if (indexOfFail(tmp1) == null) return true;
let tmp2 = sequence.slice(0);
tmp2.splice(index + 1, 1); //remove next item to failed item
if (indexOfFail(tmp2) == null) return true;
return false;
}
Here is my answer
function almostIncreasingSequence(sequence) {
if (isIncreasingSequence(sequence)) {
return true;
}
for (var i = 0; i < sequence.length > 0; i++) {
var tmpSequence = sequence.slice(0); // copy original array
tmpSequence.splice(i, 1);
if (isIncreasingSequence(tmpSequence)) {
return true;
}
}
return false;
}
function isIncreasingSequence(sequence) {
for (var i = 0; i < sequence.length - 1; i++) {
if (sequence[i] >= sequence[i + 1]) {
return false;
}
}
return true;
}
almostIncreasingSequence([1, 3, 2, 1]); // false
almostIncreasingSequence([1, 3, 2]); // true
function almostIncreasingSequence(seq) {
var bad=0
for(var i=1;i<seq.length;i++) if(seq[i]<=seq[i-1]) {
bad++
if(bad>1) return false
if(seq[i]<=seq[i-2]&&seq[i+1]<=seq[i-1]) return false
}
return true
}
My Python3 answer:
O(n) time and O(1) space
def almostIncreasingSequence(sequence):
counter = 0
for idx in range(1, len(sequence)):
# n is smaller or equal to n-1
if sequence[idx] <= sequence[idx-1]:
counter += 1
# checking if index to be checked is within bounds
if idx - 2 >= 0 and idx + 1 <= len(sequence)-1:
# n is smaller or equal to n-1 and n+1 is smaller or equal to n-1
print(sequence[idx], sequence[idx-2], sequence[idx+1], sequence[idx-1])
if sequence[idx] <= sequence[idx-2] and sequence[idx+1] <= sequence[idx-1]:
counter += 1
print(counter)
# return true if 1 or 0 in counter otherwise return false
return counter <= 1
I know post is old, but here is php solution to the problem
function almostIncreasingSequence($sequence){
$error = false;
$check_current_again = false;
for ($i = 0; $i + 1 < count($sequence); $i++) {
$next = $i + 1;
if($check_current_again){
$i = $i - 1;
}
$check_current_again = false;
if($sequence[$i] >= $sequence[$next]){
if($error){
return false;
}
$error = true;
if($i > 0 && $sequence[$i -1] >= $sequence[$i + 1]){
$check_current_again = true;
}
}
}
return true;
}
Solution of a question:
function almostIncreasingSequence(sequence) {
var inc = true;
for (var i = 0; i < sequence.length; i++) {
if (sequence[i] >= sequence[i + 1]) {
if (inc) {
inc = false;
}
else {
return false;
}
}
};
return true;
}
console.log(almostIncreasingSequence([1, 3, 2, 1])); // false
console.log(almostIncreasingSequence([1, 3, 2])); // true
I think sequence is not almost increasing if there is more than one number which is smaller than it's previous number:
function almostIncreasingSequence(sequence) {
var found = 0;
sequence.forEach((el, index) => {
var next= sequence[index + 1] || Infinity;
if (el >= next) {
found++;
}
});
return found <= 1;
}
console.log("1, 3, 2, 1: ", almostIncreasingSequence([1, 3, 2, 1]));
console.log("1, 3, 2: ", almostIncreasingSequence([1, 3, 2]));
console.log("1, 2, 5, 5, 5: ", almostIncreasingSequence([1, 2, 5, 5, 5]));
And even simpler and shorter with array.filter:
function almostIncreasingSequence(sequence) {
return sequence.filter((it, index) => it >= (sequence[index + 1] || Infinity)).length <= 1;
}
console.log("1, 3, 2, 1: ", almostIncreasingSequence([1, 3, 2, 1]));
console.log("1, 3, 2: ", almostIncreasingSequence([1, 3, 2]));
console.log("1, 2, 5, 5, 5: ", almostIncreasingSequence([1, 2, 5, 5, 5]));
console.log("1, 2, 4, 5, 5: ", almostIncreasingSequence([1, 2, 4, 5, 5]));
function Test(arr){
var set_once = false;
for (i=0; i<arr.length; i++){
if(arr[i+1] <= arr[i]){
if(!set_once){
set_once = true;
arr.splice(i+1,1);
i = i-1;
}else{
return false;
}
}
}
return true
}
Algorithm: An almost increasing sequence can only have one number that is smaller than its previous number, and it must not equal than the number before its previous number. Also, the previous number must not equal to the number after the current number.
Illustration: Consider the following 4 numbers:
a, b, c, d
a and c must not equal to each other, so are b and d. We must nest this condition within (b > c) condition.
Actual JavaScript code:
const almostIncreasingSequence = seq => {
let decrementCount = 0;
for (let i = 1; i < seq.length - 1; i ++) {
if (seq[i] <= seq[i - 1]) {
decrementCount++;
if (seq[i] <= seq[i - 2] && seq[i + 1] <= seq[i - 1]) {
return false;
}
}
}
return decrementCount <= 1;
}
Here is a solution in PHP
function almostIncreasingSequence($sequence) {
$foundOne = false;
for ($i = -1, $j = 0, $k = 1; $k < count($sequence); $k++) {
$deleteCurrent = false;
if ($sequence[$j] >= $sequence[$k])
{
if ($foundOne)
{
return false;
}
$foundOne = true;
if ($k > 1 && $sequence[$i] >= $sequence[$k])
{
$deleteCurrent = true;
}
}
if (!$foundOne)
{
$i = $j;
}
if (!$deleteCurrent)
{
$j = $k;
}
}
return true;
}
static bool almostIncreasingSequence(int[] sequence)
{
int counter = 0;
if (sequence.Length <3)
return true;
int prevNo = sequence.Min() - 1;
for (int i = 0; i < sequence.Length; i++)
{
if (counter < 2)
{
if (prevNo < sequence[i])
prevNo = sequence[i];
else
{
if (i == 0 || i == sequence.Length - 1)
{
counter += 1;
}
else if (i > 1)
{
if (sequence[i] <= sequence[i - 2])
{
if (prevNo < sequence[i + 1])
{
counter += 1;
}
else
{
counter += 2;
}
}
else
{
prevNo = sequence[i];
counter = counter + 1;
}
}
// {
if (i < sequence.Length - 2)
{
if (sequence[i] < sequence[i + 1])
{
counter = counter + 1;
prevNo = sequence[i];
}
else
{
counter += 1;
}
}
// }
if (counter >= 2)
return false;
}
}
}
return true;
}
Here is a python3 implementation of the same. took me a while. not that clean of a code
But take O(N) time and O(1) space so that's ok I guess.
In this case, I had used an approach where I maintained a counter variable and a pointer
I increased the counter by 1 each time the sequence was not in an increasing fashion.
and maintained a pointer to the index of the element which was out of sequence.
if the counter had value more than 1 then the sequence is breaking at 2 points and it almost increasing sequence can not be achieved. if the sequence was already in place then the counter would be zero.
the tricky part comes when the counter is 1
here we make use of the index variable which we maintained that is p
if the c == 1 and the index is 0 or the length of sequence then the element which is breaking the sequence is at the start or end which can be removed to obtain an increasing sequence.
and if that's, not the case. we check for the adjacent values and they are breaking any order or not.
if they are not breaking the order return True else its False. Hope I was able to help. Forgive the Bad indentation. I am new to the code editor at StackOverflow
def almostIncreasingSequence(sequence):
p = -1
c = 0
for i in range(1, len(sequence)):
if sequence[i-1] >= sequence[i]:
p = i
c += 1
if c > 1:
return False
if c == 0:
return True
if p == n -1 or p == 1:
return True
if sequence[p-1] < sequence[p+1] or sequence[p-2] < sequence[p]:
return True
return False
Here's an extremely dirty version of it.
Lately, I've been trying to make solutions that are language agnostic, so that I don't become dependent on functions for problem solving, but learn them later for whatever language I specialize in.
Perhaps one of the dirtiest ways to do it, but time complexity is O(3N) = O(N).
Space complexity is O(2N).
The logic comes from the fact that you only need to check for ONE missing element, so there is no need to do anything fancy, just save the index of that element and check the array without that element.
Because sometimes you can run into another element being the issue (particularly in the case of duplicates), you should save the index of both problem elements.
Again, extremely dirty, but it passes all test cases and time constraints.
function almostIncreasingSequence(sequence) {
let wrongindex = 0;
let nextwrongindex = 0;
for(let i = 0; i < sequence.length - 1; i++){
if(sequence[i] >= sequence[i + 1]){
wrongindex = i;
nextwrongindex = i+1;
}
}
let newArr = [];
let newArr2 = [];
for(let i = 0; i < sequence.length; i++){
if(i != wrongindex){
newArr.push(sequence[i]);
}
}
for(let i = 0; i < sequence.length; i++){
if(i != nextwrongindex){
newArr2.push(sequence[i]);
}
}
let isincreasingcount = 0;;
for(let i = 0; i < newArr.length - 1; i++){
if(newArr[i] >= newArr[i+1]){
isincreasingcount++;
}
}
for(let i = 0; i < newArr2.length -1; i++){
if(newArr2[i] >= newArr2[i+1]){
isincreasingcount++;
}
}
if(isincreasingcount > 1){
return false;
}
return true;
}
$sequence = [0, -2, 6, 8] (Expected Output: true)
$sequence = [123, -17, -5, 1, 2, 12, 41, 45] (Expected Output:
true)
$sequence = [10, 1, 2, 3, 4, 5, 6, 1] (Expected Output: false)
$sequence = [3, 5, 62, 98, 3] (Expected Output: true)
$sequence = [40, 49, 63, 10, 22, 30] (Expected Output: false)
This almostIncreasingSequence function will return the given Array is Increasing Sequence or not.
You can try the above array examples.
print_r(almostIncreasingSequence($sequence));
function almostIncreasingSequence($sequence){
$found = 0;
$status = true;
for ($i=0;$i<sizeof($sequence);$i++) {
if(($sequence[$i] <= #$sequence[$i-1]) && isset($sequence[$i-1])) {
$found++;
if($found > 1) $status = false;
if($sequence[$i] <= $sequence[$i-2] && $sequence[$i+1] <= $sequence[$i-1] && isset($sequence[$i+1])) $status = false;
}
}
return (($status == 0) ? $status : true);
}
Just for the diversity. That's how I solved it.
function almostIncreasingSequence(sequence) {
let failsSeq = new Array(sequence.length).fill(0);
for(let i=0; i<sequence.length; i++) {
if (sequence[i+1] && sequence[i] >= sequence[i+1]) {
failsSeq[i] += 1;
if (sequence[i+2] && sequence[i] >= sequence[i+2]) {
failsSeq[i] += 1;
}
if (sequence[i-1] && sequence[i+1] && sequence[i-1]>=sequence[i+1]) {
failsSeq[i] += 1;
}
}
}
const failsTotal = failsSeq.reduce( (acc, currValue) => acc + currValue);
const failSingle = failsSeq.filter( (item) => item >= 2 ).length;
if (failSingle === 1 && failsTotal === 2) {
return true;
}
return failsTotal > 1 ? false : true;
}
for eg 1,2,[5,3],6
We can solve this by 2 pointers, p2 will be ahead of p1 by 1 at the beginning. Once we found that, from the eg, 5 > 3, we need to skip each and check if the sequence is still valid, for that reason we call increasingSeq(), and skip 5 by (p1 -1). Then we skip 3 by (p2 + 1).
Once we skip those we start comparing the sequence again.
function almostIncreasingSequence(sequence) {
if (sequence.length < 2) return true;
let p1 = 0;
let p2 = 1;
while(p2 < sequence.length) {
if (sequence[p1] >= sequence[p2]) {
const a = increasingSeq(sequence, p1 - 1, p2);
const b = increasingSeq(sequence, p1, p2 +1 )
return a || b
}
p1 = p2;
p2++
}
return true;
}
function increasingSeq(sequence, p1, p2) {
while(p2 < sequence.length) {
if (sequence[p1] >= sequence[p2]) return false;
p1 = p2;
p2++
}
return true;
}
boolean almostIncreasingSequence(int[] sequence) {
int n = sequence.length;
if (n == 2)
{
return true;
}
int count = 0;
boolean result = true;
for (int i = 0; i < sequence.length - 1; i++)
{
if (sequence[i] >= sequence[i+1])
{
count++;
if (i != 0 && sequence[i-1] >= sequence[i+1])
{
result = false;
}
if (i < n-2 && sequence[i] < sequence[i+2])
{
result = true;
}
if (i == n - 2)
{
result = true;
}
}
}
return (count < 2 && result);
}
Here is a complete working solution:
function almostIncreasingSequence($s)
{
$bad=0;
for($i=1;$i<count($s);$i++)
{
if($s[$i]<=$s[$i-1]) $bad++;
if($bad>1) return false;
if(isset($s[$i+1]) && isset($s[$i-2]) && $s[$i]<=$s[$i-2] && $s[$i+1]<=$s[$i-1]) return false;
}
return true;
}
This is my optimized solution with python:
def solution(sequence):
if len(sequence) > 2:
for i in range(len(sequence)-1):
if sequence[i]>sequence[i+1]:
news = sequence[:i]+sequence[i+1:]
if news == sorted(news) and len(set(news)) == len(news):
return True
else:
news = sequence[:i+1]+sequence[i+2:]
if news == sorted(news) and len(set(news)) == len(news):
return True
return False
else:
return True
I've checked out that most proposals fails with the new tests added to codeSignal. My approach is not quite optimal but it's easy to understand.
First, I store into a hashmap the problematic indexes (the current and the previous one). After that you can run simulations of the array without the problematic items. It just simply minimizes the brute force approach and it passes all the test even with high amount of items.
Time complexity: O(N+N)
Space complexity: O(1)
Tests passed: 38/38.
Sample tests:
19/19
Hidden tests:
19/19
Score:
300/300
Edited: I added a "break" after first problematic number encountered in order to just handle the first issue. So time complexity now is better.
bool almostIncreasingSequence(vector<int> sequence) {
int length = sequence.size();
if (length < 2) {
return false;
}
// Store invalid indexes
unordered_map<int, int> m;
for(int i=1;i<length;++i) {
if (sequence[i-1] >= sequence[i]) {
m[i-1]++;
m[i]++;
break; // new added
}
}
// Scan invalid indexes
for(auto it : m) {
int prev = -1;
int numInvalid = 0;
const int id = it.first;
// Simulate
for(int i=0;i<length;++i) {
if (id!=i) { // Do not add the problematic one
if (prev != -1 && prev >= sequence[i]) {
++numInvalid;
break;
}
prev = sequence[i];
}
}
if (numInvalid == 0) {
return true;
}
}
return false;
}
Here is my PHP solution:
function almostIncreasingSequence($sequence) {
for($i=0;$i<count($sequence);$i++) {
$input = $sequence;
array_splice($input, $i, 1);
if(count($input) == count(array_unique($input))) {
$solution = $input;
sort($input);
if($solution == $input) {
return true;
}
}
}
return false;
}
My javascript answer for strictly increasing sequence.
function solution(sequence) {
for(let i =0;i<sequence.length;i++){
// first iteration
if((sequence[i]-sequence[i+1])>=0){
sequence.splice((i),1);
console.log('5', sequence);
// check again
for(let i = 0;i<sequence.length;i++){
if((sequence[i]-sequence[i+1])>=0){
console.log('9', sequence);
return false;
}
}
}
};
return true
}
boolean solution(int[] sequence) {
int count = 0;
for (int i = 1; i < sequence.length; i++) {
if (sequence[i] <= sequence[i-1]) {
// Increase count if we found a replace.
// return false if we found more than one
// replacements
count++;
if (count > 1) {
return false;
}
// Make sure you are within bounds of the array
// compare current index value with with previous
// two indices.
// finally compare values before and after the current
// index.
if (i - 2 > -1 && i+1 < sequence.length
&& sequence[i] <= sequence[i-2]
&& sequence[i+1] <= sequence[i-1]) {
return false;
}
}
}
return true;
}
I am in mid of my JavaScript session. Find this code in my coding exercise. I understand the logic but I didn't get this map[nums[x]] condition.
function twoSum(nums, target_num) {
var map = [];
var indexnum = [];
for (var x = 0; x < nums.length; x++)
{
if (map[nums[x]] != null)
// what they meant by map[nums[x]]
{
index = map[nums[x]];
indexnum[0] = index+1;
indexnum[1] = x+1;
break;
}
else
{
map[target_num - nums[x]] = x;
}
}
return indexnum;
}
console.log(twoSum([10,20,10,40,50,60,70],50));
I am trying to get the Pair of elements from a specified array whose sum equals a specific target number. I have written below code.
function arraypair(array,sum){
for (i = 0;i < array.length;i++) {
var first = array[i];
for (j = i + 1;j < array.length;j++) {
var second = array[j];
if ((first + second) == sum) {
alert('First: ' + first + ' Second ' + second + ' SUM ' + sum);
console.log('First: ' + first + ' Second ' + second);
}
}
}
}
var a = [2, 4, 3, 5, 6, -2, 4, 7, 8, 9];
arraypair(a,7);
Is there any optimized way than above two solutions? Can some one explain the first solution what exactly map[nums[x]] this condition points to?
Using HashMap approach using time complexity approx O(n),below is the following code:
let twoSum = (array, sum) => {
let hashMap = {},
results = []
for (let i = 0; i < array.length; i++){
if (hashMap[array[i]]){
results.push([hashMap[array[i]], array[i]])
}else{
hashMap[sum - array[i]] = array[i];
}
}
return results;
}
console.log(twoSum([10,20,10,40,50,60,70,30],50));
result:
{[10, 40],[20, 30]}
I think the code is self explanatory ,even if you want help to understand it,let me know.I will be happy enough to for its explanation.
Hope it helps..
that map value you're seeing is a lookup table and that twoSum method has implemented what's called Dynamic Programming
In Dynamic Programming, you store values of your computations which you can re-use later on to find the solution.
Lets investigate how it works to better understand it:
twoSum([10,20,40,50,60,70], 50)
//I removed one of the duplicate 10s to make the example simpler
In iteration 0:
value is 10. Our target number is 50. When I see the number 10 in index 0, I make a note that if I ever find a 40 (50 - 10 = 40) in this list, then I can find its pair in index 0.
So in our map, 40 points to 0.
In iteration 2:
value is 40. I look at map my map to see I previously found a pair for 40.
map[nums[x]] (which is the same as map[40]) will return 0.
That means I have a pair for 40 at index 0.
0 and 2 make a pair.
Does that make any sense now?
Unlike in your solution where you have 2 nested loops, you can store previously computed values. This will save you processing time, but waste more space in the memory (because the lookup table will be needing the memory)
Also since you're writing this in javascript, your map can be an object instead of an array. It'll also make debugging a lot easier ;)
function twoSum(arr, S) {
const sum = [];
for(let i = 0; i< arr.length; i++) {
for(let j = i+1; j < arr.length; j++) {
if(S == arr[i] + arr[j]) sum.push([arr[i],arr[j]])
}
}
return sum
}
Brute Force not best way to solve but it works.
Please try the below code. It will give you all the unique pairs whose sum will be equal to the targetSum. It performs the binary search so will be better in performance. The time complexity of this solution is O(NLogN)
((arr,targetSum) => {
if ((arr && arr.length === 0) || targetSum === undefined) {
return false;
} else {
for (let x = 0; x <=arr.length -1; x++) {
let partnerInPair = targetSum - arr[x];
let start = x+1;
let end = (arr.length) - 2;
while(start <= end) {
let mid = parseInt(((start + end)/2));
if (arr[mid] === partnerInPair) {
console.log(`Pairs are ${arr[x]} and ${arr[mid]} `);
break;
} else if(partnerInPair < arr[mid]) {
end = mid - 1;
} else if(partnerInPair > arr[mid]) {
start = mid + 1;
}
}
};
};
})([0,1,2,3,4,5,6,7,8,9], 10)
function twoSum(arr, target) {
let res = [];
let indexes = [];
for (let i = 0; i < arr.length - 1; i++) {
for (let j = i + 1; j < arr.length; j++) {
if (target === arr[i] + arr[j] && !indexes.includes(i) && !indexes.includes(j)) {
res.push([arr[i], arr[j]]);
indexes.push(i);
indexes.push(j);
}
}
}
return res;
}
console.log('Result - ',
twoSum([1,2,3,4,5,6,6,6,6,6,6,6,6,6,7,8,9,10], 12)
);
Brute force.
const findTwoNum = ((arr, value) => {
let result = [];
for(let i= 0; i< arr.length-1; i++) {
if(arr[i] > value) {
continue;
}
if(arr.includes(value-arr[i])) {
result.push(arr[i]);
result.push(value-arr[i]);
break;;
}
}
return result;
});
let arr = [20,10,40,50,60,70,30];
const value = 120;
console.log(findTwoNum(arr, value));
OUTPUT : Array [50, 70]
function twoSum(arr){
let constant = 17;
for(let i=0;i<arr.length-2;i++){
for(let j=i+1;j<arr.length;j++){
if(arr[i]+arr[j] === constant){
console.log(arr[i],arr[j]);
}
}
}
}
let myArr = [2, 4, 3, 5, 7, 8, 9];
function getPair(arr, targetNum) {
for (let i = 0; i < arr.length; i++) {
let cNum = arr[i]; //my current number
for (let j = i; j < arr.length; j++) {
if (cNum !== arr[j] && cNum + arr[j] === targetNum) {
let pair = {};
pair.key1 = cNum;
pair.key2 = arr[j];
console.log(pair);
}
}
}
}
getPair(myArr, 7)
let sumArray = (arr,target) => {
let ar = []
arr.forEach((element,index) => {
console.log(index);
arr.forEach((element2, index2) => {
if( (index2 > index) && (element + element2 == target)){
ar.push({element, element2})
}
});
});
return ar
}
console.log(sumArray([8, 7, 2, 5, 3, 1],10))
Use {} hash object for storing and fast lookups.
Use simple for loop so you can return as soon as you find the right combo; array methods like .forEach() have to finish iterating no matter what.
And make sure you handle edges cases like this: twoSum([1,2,3,4], 8)---that should return undefined, but if you don't check for !== i (see below), you would erroneously return [4,4]. Think about why that is...
function twoSum(nums, target) {
const lookup = {};
for (let i = 0; i < nums.length; i++) {
const n = nums[i];
if (lookup[n] === undefined) {//lookup n; seen it before?
lookup[n] = i; //no, so add to dictionary with index as value
}
//seen target - n before? if so, is it different than n?
if (lookup[target - n] !== undefined && lookup[target - n] !== i) {
return [target - n, n];//yep, so we return our answer!
}
}
return undefined;//didn't find anything, so return undefined
}
We can fix this with simple JS object as well.
const twoSum = (arr, num) => {
let obj = {};
let res = [];
arr.map(item => {
let com = num - item;
if (obj[com]) {
res.push([obj[com], item]);
} else {
obj[item] = item;
}
});
return res;
};
console.log(twoSum([2, 3, 2, 5, 4, 9, 6, 8, 8, 7], 10));
// Output: [ [ 4, 6 ], [ 2, 8 ], [ 2, 8 ], [ 3, 7 ] ]
Solution In Java
Solution 1
public static int[] twoNumberSum(int[] array, int targetSum) {
for(int i=0;i<array.length;i++){
int first=array[i];
for(int j=i+1;j<array.length;j++){
int second=array[j];
if(first+second==targetSum){
return new int[]{first,second};
}
}
}
return new int[0];
}
Solution 2
public static int[] twoNumberSum(int[] array, int targetSum) {
Set<Integer> nums=new HashSet<Integer>();
for(int num:array){
int pmatch=targetSum-num;
if(nums.contains(pmatch)){
return new int[]{pmatch,num};
}else{
nums.add(num);
}
}
return new int[0];
}
Solution 3
public static int[] twoNumberSum(int[] array, int targetSum) {
Arrays.sort(array);
int left=0;
int right=array.length-1;
while(left<right){
int currentSum=array[left]+array[right];
if(currentSum==targetSum){
return new int[]{array[left],array[right]};
}else if(currentSum<targetSum){
left++;
}else if(currentSum>targetSum){
right--;
}
}
return new int[0];
}
function findPairOfNumbers(arr, targetSum) {
var low = 0, high = arr.length - 1, sum, result = [];
while(low < high) {
sum = arr[low] + arr[high];
if(sum < targetSum)
low++;
else if(sum > targetSum)
high--;
else if(sum === targetSum) {
result.push({val1: arr[low], val2: arr[high]});
high--;
}
}
return (result || false);
}
var pairs = findPairOfNumbers([1,2,3,4,4,5], 8);
if(pairs.length) {
console.log(pairs);
} else {
console.log("No pair of numbers found that sums to " + 8);
}
Simple Solution would be in javascript is:
var arr = [7,5,10,-5,9,14,45,77,5,3];
var arrLen = arr.length;
var sum = 15;
function findSumOfArrayInGiven (arr, arrLen, sum){
var left = 0;
var right = arrLen - 1;
// Sort Array in Ascending Order
arr = arr.sort(function(a, b) {
return a - b;
})
// Iterate Over
while(left < right){
if(arr[left] + arr[right] === sum){
return {
res : true,
matchNum: arr[left] + ' + ' + arr[right]
};
}else if(arr[left] + arr[right] < sum){
left++;
}else{
right--;
}
}
return 0;
}
var resp = findSumOfArrayInGiven (arr, arrLen, sum);
// Display Desired output
if(resp.res === true){
console.log('Matching Numbers are: ' + resp.matchNum +' = '+ sum);
}else{
console.log('There are no matching numbers of given sum');
}
Runtime test JSBin: https://jsbin.com/vuhitudebi/edit?js,console
Runtime test JSFiddle: https://jsfiddle.net/arbaazshaikh919/de0amjxt/4/
function sumOfTwo(array, sumNumber) {
for (i of array) {
for (j of array) {
if (i + j === sumNumber) {
console.log([i, j])
}
}
}
}
sumOfTwo([1, 2, 3], 4)
function twoSum(args , total) {
let obj = [];
let a = args.length;
for(let i = 0 ; i < a ; i++){
for(let j = 0; j < a ; j++){
if(args[i] + args[j] == total) {
obj.push([args[i] , args[j]])
}
}
}
console.log(obj)}
twoSum([10,20,10,40,50,60,70,30],60);
/* */