So I just started studying the Big O notation on my own. I thought I had understood the basics till I wrote a function to check for prime numbers and tried to figure out its time complexity. Here's the code:
function isPrime(num){
if (num === 1 || num%1 !== 0){ //Checks if num is 1 or decimal
return false;
}
else{
for (var i = 2; i < num; i++) {
if (num%i === 0 && i!== 1){ //Checks if any numbers from 2 to are divisible by num
return false
}
}
}
return true;
}
console.log(isPrime(6));
First thing that confused me is whether multiple conditions inside an if statement make any difference or it is just counted once? And then notice I have three return statements. Does that mean I have to include that last line of code where I pass a number to the function to evaluate its time-complexity? Or can I do it without a passed value and calculate for different cases?
function isPrime(n){
if (n === 1 || n%1 !== 0){ //Checks if num is 1 or decimal
return false;
}
for (var i = 2; i < n; i++) {
if (n%i === 0){
return false
}
}
return true;
}
I have made some small refactoring which doesn't change the complexity but makes the code more readable for struggling with Big-O.
So for n > 1, n : orime, the number of operations is:
So the complexity of your algorithm is O(n).
Related
I want to write a function that finds the next largest palindrome for a given positive integer. For example:
Input: 2
Output: 3 (every single digit integer is a palindrome)
Input: 180
Output: 181
Input: 17
Output: 22
My try
function nextPalindrome(num) {
let input = num;
let numToStringArray = input.toString().split('');
let reversedArray = numToStringArray.reverse();
if (numToStringArray.length < 2) {
return Number(numToStringArray) + 1;
} else {
while (numToStringArray !== reversedArray) {
// numToStringArray = num.toString().split('');
// reversedArray = numToStringArray.reverse();
num += 1;
}
return numToStringArray.join('');
}
}
As a beginner, I thought that the numToStringArray would constantly increment by 1 and check for whether the while-statement is true.
Unfortunately it doesn't. I commented out two lines in the while-statement because they seemed somewhat redundant to me. Thanks to everyone reading or even helping me out!
The reason your code doesn't work is because you don't have any code updating the conditions of your while loop. So if you enter it once, it will loop indefinitely. You need to do something inside of the while loop that might make the condition false the next time through the loop, like so:
function getReverse(num) {
// get the reverse of the number (in positive number form)
let reversedNum = +Math.abs(num).toString().split("").reverse().join("");
// keep negative numbers negative
if (num < 0) { reversedNum *= -1; }
return reversedNum;
}
function nextPalindrome(num) {
// if single digit, simply return the next highest integer
if (num >= -10 && num < 9) {
return num+1;
}
else {
while(num !== getReverse(num)) {
num += 1;
}
return num;
}
}
console.log(nextPalindrome(3));
console.log(nextPalindrome(17));
console.log(nextPalindrome(72));
console.log(nextPalindrome(180));
console.log(nextPalindrome(1005));
console.log(nextPalindrome(-150));
console.log(nextPalindrome(-10));
You could also solve this pretty cleanly using recursion, like so:
function getReverse(num) {
// get the reverse of the number (in positive number form)
let reversedNum = +Math.abs(num).toString().split("").reverse().join("");
// keep negative numbers negative
if (num < 0) { reversedNum *= -1; }
return reversedNum;
}
function nextPalindrome(num) {
// if single digit, simply return the next highest integer
if (num >= -10 && num < 9) {
return num+1;
}
else if(num === getReverse(num)) {
return num;
}
else {
// if not the same, recurse with n + 1
return nextPalindrome(num + 1)
}
}
console.log(nextPalindrome(3));
console.log(nextPalindrome(17));
console.log(nextPalindrome(72));
console.log(nextPalindrome(180));
console.log(nextPalindrome(1005));
console.log(nextPalindrome(-150));
console.log(nextPalindrome(-10));
The code here check for prime numbers from 2 to n:
<script>
function showPrimes(n) {
for (let i = 2; i < n; i++) {
if (!isPrime(i)) continue;
alert(i); // a prime
}
}
function isPrime(n) {
for (let i = 2; i < n; i++) {
if ( n % i == 0) return false;
}
return true;
}
</script>
But I don't understand why it works for number 2 and return false when both n and i equal to 2 while it doesn't happen with other prime numbers. I am new to javascript(and programming in general) and from what I understood this code take the i from the first iteration in the first loop(on the "showPrimes" function) and put it on "isPrime" function as a parameter and in that function it becomes the "n" in the 'if' condition and it checks if there is a remainder when it gets divided by the i from the loop of "isPrime" so (n % i == 0) should be (2 % 2 == 0) in the first iteration, Is that right? if so why does it works just like it work for other prime numbers which clearly become false unlike (2 % 2 == 0) which is true...
What I am missing here?. Sorry if this is an obvious/stupid question, it is the first time I am learning anything related to programming.
function isPrime(n) {
for (let i = 2; i < n; i++) {
When n=2; i=2; The above loop will not be entered.
I've started reading Eloquent Javascript, and there's an exercise about making a recursive function to check for evenness.
I've made it in a couple different ways, it's quite simple, but for some reason I can't get it to work with negative numbers anymore. I had it working, then probably accidentally changed something, and now it only works for positives.
Could you please tell me why this code is 'wrong'?
(textfield.append just prints something to a textfield I've made in an html/css-document, so I can save the exercises in some kind of 'program'.)
function evencheck(n){
if (n == 0){
$('#textfield').append('Even');
}
if (n == 1 || n == -1){
$('#textfield').append('Uneven');
}
else{
if(n > 1){
n -= 2;
evencheck(n);
}
if(n < -1){
n += 2;
evencheck(n);
}
}
}
I know it can be written shorter, I've made a shorter form of it, but that didn't work on negatives either.
I know the problem is a stack overflow, but why is this happening?
not an answer but an extended comment
function evencheck(n){
if (n == 0){
return $('#textfield').append('Even');
}
if (n == 1 || n == -1){
return $('#textfield').append('Uneven');
}
return evencheck(n > 1? n-2 : n+2);
}
The upper code will probably be faster, as the compiler can optimize it to:
function evencheck(n){
while(true){
if (n == 0){
return $('#textfield').append('Even');
}
if (n == 1 || n == -1){
return $('#textfield').append('Uneven');
}
n = n>1? n -2 : n+2;
}
}
So youre not filling the function stack ( really huge numbers possible) , and its actually really fast.
More about that
Your code seems to work, except for large numbers. Try it with something like -12 or 10 works fine. When you input 30000 it hangs itself. Probably because you call the method recursively too many times.
const
inputElement = document.getElementById('number-input'),
checkTrigger = document.getElementById('check-number')
resultLog = document.getElementById('result');
function evencheck(n){
if (n == 0){
resultLog.textContent = `${n} is event.`;
}
if (n == 1 || n == -1){
resultLog.textContent = `${n} is unevent.`;
}
else{
if(n > 1){
n -= 2;
evencheck(n);
}
if(n < -1){
n += 2;
evencheck(n);
}
}
}
function checkInputNumber(event) {
const
numberToCheck = parseInt(inputElement.value);
evencheck(numberToCheck);
}
checkTrigger.addEventListener('click', checkInputNumber);
$('#evenrecursive').click(function(){ $('#textfield').append("<p style ='color:blue'>new command: check if number is even.</p>"); var n = prompt('pick a number', ''); evencheck(n); });
#evenrecursive {
border: 1px solid;
min-height: 20px;
width: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="number-input" type="number" />
<button type="button" id="check-number">check</button>
<p id="result"></p>
<div id="evenrecursive">click me for prompt.</div>
I've added your trigger and the problem you're having is type coercion. When the initial value of n is "-10" the code winds up in n += 2, this comes down to n = "-10" + 2 which is "-102" and thus your code never reaches the end.
now it only works for positives. why is this happening?
You might be passing a string, in which case n += 2 does do string concatenation instead of number addition (whereas -= 2 always casts to a number). Try adding
if (typeof n != "number") throw new TypeError("n must be a number");
in the first line of the function, and make sure you do use parseInt or some other suitable parsing method if you take a string input from the user.
Instructions: Write a function called "modulo". Given 2 numbers, "modulo" returns the remainder after dividing num1 by num2.
This is my code so far. When I run it on repl.it it gives the correct remainder, but when I submit the program it goes into an infinite loop and I have no clue why. I figure the return functions in the for loop would just automatically exit it. Any help would be appreciated, thanks. Basically I'm adding number2 constantly until it either hits number 1 or goes higher than it. If it goes higher, I subtract number 2 once, and find the difference.
function modulo(num1, num2) {
if(num1 === 0) {
return 0;
}
if(num2 === 0) {
return NaN;
}
if(isNaN(num1) === true || isNaN(num2) === true) {
return NaN;
}
var i = 0;
for( i = 0; i <= num1;) {
i += num2;
if(i === num1) {
return 0;
}
else if(i > num1) {
i = i - num2;
console.log(i, num1);
return num1 - i;
}
}
}
var output = modulo(25, 4);
console.log(output);
function modulo(num1, num2) { var div = num1/num2;
var remainder = div - Math.floor(div); // gives the decimal point value left out from the division
return Math.round(remainder * num2); // multiplies the remainder with num2 and gives a whole number value
}
This is pretty simpler and should work all times
I'm not entirely sure where the infinite loop is showing up; I've plugged your code into console and I can call the function just fine. What site are you using to validate?
Also, without altering too much of your exercise, I'd like to point out a couple of tiny areas where you can consolidate your code to improve readability:
if(num2 === 0) {
return NaN;
}
if(isNaN(num1) === true || isNaN(num2) === true) {
return NaN;
}
can be distilled down into
if (num2 === 0 || isNaN(num1) || isNaN(num2)) {
return NaN;
}
because in JavaScript, booleans work in such a way that everything with a real value is considered to be true, i.e. isNaN(num1) and isNaN(num2) are "true" by default.
Also, remember that you can use all your assignment operators; it's completely optional, but since you used one (i += num2;), I figured I'd point out that you could use another further down the code (i -= num2;).
Happy coding! :)
It could be another option:
function modulo(num1, num2) {
if(isNaN(num1) || isNaN(num2) ) {
return NaN;
}
var strResult = (num1/num2).toString();
var decimalPart =
parseFloat(strResult.substr(strResult.indexOf(".")));
var remainder = Math.round(decimalPart*num2);
return remainder;
}
console.log(modulo(77,9), (77%9)); // 5
console.log(modulo(549,123), (549%123)); // 57
console.log(modulo(33,6), (33%6)); // 3
Is there an efficient way to check if number belongs to Fibonacci sequence?
I've seen many examples with a loop that creates the sequence in an array and checks every time if newly generated number of the sequence is equal to the input number. Is there another way?
http://www.geeksforgeeks.org/check-number-fibonacci-number/
This link details that there is a special quality about fibonacci numbers that means that a number is Fibonacci if and only if one or both of (5*n2 + 4) or (5*n2 – 4) is a perfect square.
So,
function (num) {
if (isSquare(5*(num*num)-4) || isSquare(5*(num*num)+4)) {
return true;
} else { return false; }
}
Then isSquare would just be a simple checking function.
Edit: Worth noting that while this is a much more efficient and easy way to find fibonacci numbers, it does have an upper bound. At about the 70th Fibonacci number and above, you may see issues because the numbers are too large.
function isFibonacci(num, a = 0, b = 1) {
if(num === 0 || num === 1) {
return true;
}
let nextNumber = a+b;
if(nextNumber === num) {
return true;
}
else if(nextNumber > num) {
return false;
}
return isFibonacci(num, b, nextNumber);
}
function isPerfectSquare(n) {
return n > 0 && Math.sqrt(n) % 1 === 0;
};
//Equation modified from http://www.geeksforgeeks.org/check-number-fibonacci-number/
function isFibonacci(numberToCheck)
{
// numberToCheck is Fibinacci if one of 5*n*n + 4 or 5*n*n - 4 or both
// is a perferct square
return isPerfectSquare(5*numberToCheck*numberToCheck + 4) ||
isPerfectSquare(5*numberToCheck*numberToCheck - 4);
}
for(var i = 0; i<= 10000; ++i) {
console.log(i + " - " + isFibonacci(i));
}
This will most likely fail for larger numbers though.
def is_squared(number):
temp_root = math.sqrt(number);
temp_root = int(temp_root);
return (temp_root * temp_root == number);
def check_all_fibo(test_number_list):
result_fibo_list = [];
for item in test_number_list:
if item==0 or item == 1 or item == 2:
result_fibo_list.append(item);
continue;
if is_squared(5 * item * item - 4) or is_squared(5 * item * item + 4):
result_fibo_list.append(item);
return result_fibo_list;
this is a python implementation by me. But keep in mind, the formula only works when the fib is not too large.
The Fibonacci sequence is a series of numbers where a number is the addition of the last two numbers, starting with 0, and 1. Th following js function is explaining this.
function isFabonacci(n) {
if (n === 1 || n === 0) {
return true;
}
let firstPrevNumber = n - 1;
let secondPrevNumber = n - 2;
return (firstPrevNumber + secondPrevNumber === n);
}
// isFabonacci(2) -> false
// isFabonacci(3) -> true