Showing posts with label DSA. Show all posts
Showing posts with label DSA. Show all posts

Find Wether a Given Number is Power of 2.

Determining if a number is a power of 2 is a common problem in computer science and programming. A number is considered a power of 2 if it can be expressed as 2^n, where n is a non-negative integer. For example, the numbers 1, 2, 4, 8, 16, and so on are all powers of 2.

In this post, we will explore two approaches to solve this problem: the normal approach and the bitwise approach.

Problem: Given an integer n, determine whether it is a power of two.

Example:
Input:  8  
Output: true  
Explanation: 8 = 2^3  It is a power of 2

Input:  6  
Output: false  
Explanation: 6 is not a power of 2

Approach 1: Brute Force Loop.

Keep dividing the number by 2. If at the end, you reach 1, then it's a power of 2.
If at any point, it's not divisible by 2, return false.

Steps:
  • If n == 0, return false
  • While n % 2 == 0, divide n by 2
  • If n == 1 after loop → power of 2
Example Code:

        
// C++ Example: Find Power of 2
#include <iostream>
using namespace std;

bool isPowerOfTwoLoop(int n) {
    if (n <= 0) return false; 
    while (n % 2 == 0) { 
        n = n / 2; 
    }
    return n == 1; 
}

int main() {
    int number;
    cout << "Enter a number: ";
    cin >> number;

    if (isPowerOfTwoLoop(number)) {
        cout << number << " is a power of 2." << endl;
    } else {
        cout << number << " is not a power of 2." << endl;
    }

    return 0;
}
Output:

8 is a power of 2.

  • Time Complexity: O(log n)
  • Space Complexity: O(1)

Approach 2: Bit Manipulation Approach.

A number is a power of two if it can be expressed as 2^n, where n is a non-negative integer. In binary representation, powers of two have a unique property: they have exactly one bit set to 1. 

For example:
1  = 0001   → 2^0  
2  = 0010   → 2^1  
4  = 0100   → 2^2  
8  = 1000   → 2^3  
16 = 10000  → 2^4  

This property allows us to efficiently check if a number is a power of two using bit manipulation.

To determine if a number n is a power of two using bit manipulation, we can use the following approach:
1. Check if n is greater than zero: Powers of two are positive numbers.
2. Use the expression (n&(n-1): This expression will be zero if n is a power of two. The reason behind this is that subtracting 1 from a power of two flips all the bits after the rightmost set bit (the only 1 in the binary representation). For example:
  • For n = 4 (0100), n-1 = 3 (0011)
  • The bitwise AND operation: 0100 & 0011 = 0000
Now, let's implement this logic in C++, Python, and Java.

Example Code:

        
#include <iostream>

bool isPowerOfTwo(int n) {
    return (n > 0) && ((n & (n - 1)) == 0);
}

int main() {
    int number = 8;
    if (isPowerOfTwo(number)) {
        std::cout << number << " is a power of two." << std::endl;
    } else {
        std::cout << number << " is not a power of two." << std::endl;
    }
    return 0;
}
Output:

8 is a power of two.

  • Time Complexity: O(l)
  • Space Complexity: O(1)

Find If a Number is Even or Odd Using Bitwise Operator.

Understanding whether a number is even or odd is one of the most common tasks in programming. While most beginners use the arithmetic modulus operator (%), there’s a faster and more efficient alternative the bitwise AND operator (&).

In this post, we'll explore both approaches, compare them, and understand why bitwise is better.

Approach 1: Using Arithmetic Operator.

The most common and straightforward method is using the modulus operator (%). If a number divided by 2 leaves a remainder of 0, it's even. Otherwise, it's odd.

if (n % 2 == 0)  Even  
else  Odd

Example Code:

// C++ Example: Find Number is Odd or Even
#include <iostream>
using namespace std;

void checkEvenOrOdd_Arithmetic(int n) {
    if (n % 2 == 0)
        cout << n << " is Even" << endl;
    else
        cout << n << " is Odd" << endl;
}
        
Output:

6 is Even

Approach 2: Using Bitwise AND Operator.

A faster and smarter way to check if a number is even or odd is using bitwise operators.
The & operator performs a bit-by-bit comparison between two numbers.
For each bit, it returns:
  • 1 if both bits are 1
  • 0 otherwise

When you perform n & 1, you're checking the Least Significant Bit (LSB) of the number.
  • If LSB is 0 → number is even
  • If LSB is 1 → number is odd
Because the binary of even number always end with 0 and binary of odd number always end with 1. Let's understand this with few examples:

Example 1: 
Number = 4
Binary of 4: 0100
Binary of 1: 0001

    0100
AND 0001
  = 0000  0  Even

Example 2:
Number = 7
Binary of 7: 0111
Binary of 1: 0001

    0111
AND 0001
  = 0001  1  Odd

Example Code:

        
//C++ Example: Find Even and Odd Using Bitwise AND
#include <iostream>
using namespace std;

void checkEvenOrOdd_Bitwise(int n) {
    if (n & 1)
        cout << n << " is Odd" << endl;
    else
        cout << n << " is Even" << endl;
}

int main() {
    checkEvenOrOdd_Bitwise(4);
    return 0;
}
Output:

6 is Even


Using n & 1 is a fast and efficient way to check if a number is even or odd by examining its last binary bit. It's a foundational concept in bit manipulation that helps build strong binary thinking.

 

Bit Manipulation Introduction.

Bit Manipulation is one of the most powerful and efficient techniques in programming. It involves working directly with binary digits (0s and 1s) using special operators called bitwise operators.

You may not realize it, but every number in your computer is stored in binary, and by manipulating these bits smartly, you can solve many problems faster and with less memory.

In this article, we’ll break down what bits are, how to convert between decimal and binary, and how to use bitwise operators with simple examples. We’ll also explain the concept of 2’s complement, which is used to represent negative numbers in binary.

What is a Bit?

A bit (short for binary digit) is the smallest unit of data in a computer. It can have only two possible values:
  • 0 (OFF)
  • 1 (ON)
All information in a computer — numbers, characters, images — is stored using bits. Multiple bits are grouped together to represent more complex data. For example:
  • 1 Byte = 8 bits
  • 5 in binary (8-bit) = 00000101

What is Bit Manipulation?

Bit Manipulation is a programming technique that involves working directly with the individual bits (0s and 1s) of a number using special operators called bitwise operators.

In simple terms, it's a way to perform fast and efficient operations by changing or checking the binary form of numbers — the language that computers understand best.

Bit manipulation helps in:
  • Optimizing performance
  • Saving memory using bit flags or masks
  • Solving mathematical and logical problems more efficiently

It’s widely used in competitive programming, system-level code, and interview problem-solving.

Before diving into bit manipulation techniques, it’s important to understand how numbers are represented in binary form. Since bit manipulation deals with binary digits (bits) directly, knowing how to convert between decimal and binary is the foundation.

Decimal to Binary Conversion.

To convert a decimal number to binary, we use repeated division by 2.
Steps:
  • Divide the number by 2.
  • Record the remainder (it will be 0 or 1).
  • Continue dividing the quotient by 2 until it becomes 0.
  • The binary number is the reverse order of the remainders.

Example: Convert 13 to Binary
13 ÷ 2 = 6 remainder 1  
6 ÷ 2 = 3 remainder 0  
3 ÷ 2 = 1 remainder 1  
1 ÷ 2 = 0 remainder 1

 Binary = 1101
So, 13 in binary is 1101.

Binary to Decimal Conversion

To convert a binary number to decimal, we multiply each bit by 2 raised to the power of its position (starting from the right, index 0).
Steps:
  • Start from the rightmost bit.
  • Multiply each bit by 2^position.
  • Sum all the results.

Example: Convert 1010 to Decimal
= 1×2³ + 0×2² + 1×2¹ + 0×2  
= 8 + 0 + 2 + 0  
= 10
So, 1010 in binary is 10 in decimal.

Now that you know how to convert a decimal number to binary and how to represent numbers in binary form, it's the right time to understand Bitwise Operators.

Bitwise Operators.

Bitwise operators allow us to directly manipulate individual bits of binary numbers. These operators form the backbone of bit manipulation techniques used in coding problems and optimization.

Let’s explore each bitwise operator with simple examples.

1. Bitwise AND (&)- The AND operator compares two bits and returns 1 only if both bits are 1; otherwise, it returns 0.


Truth Table of Bitwise AND

A B A & B
0 0 0
0 1 0
1 0 0
1 1 1

Example:
5 = 0101  
3 = 0011  
5 & 3 = 0001  1

2. Bitwise OR (|)- The OR operator returns 1 if at least one of the bits is 1.

Truth Table of Bitwise OR

A B A | B
0 0 0
0 1 1
1 0 1
1 1 1

Example:
5 = 0101  
3 = 0011  
5 | 3 = 0111  7

3. Bitwise XOR (^)- The XOR (exclusive OR) operator returns 1 only if the two bits are different.

Truth Table of Bitwise XOR

A B A ^ B
0 0 0
0 1 1
1 0 1
1 1 0

Example:
5 = 0101  
3 = 0011  
5 ^ 3 = 0110  6

4. Bitwise NOT (~)- The NOT operator flips each bit:
  • 0 becomes 1
  • 1 becomes 0
However, in most programming languages (like C++, Java, Python), numbers are stored in 2’s complement format, so applying ~ to a number results in -(n + 1). At the end of this article, we have explained 2's Complement in detail.
Example:
~5 = -(5 + 1) = -6

Let's break it down:
5   = 00000101  
~5  = 11111010 (in 8-bit)  which is -6 in 2s complement

5. Left Shift (<<)- The left shift operator shifts bits to the left by a given number of positions. Each left shift is equivalent to multiplying the number by 2^n.

Example:
5 << 1 = 10  
Binary: 0101 << 1  1010

6. Right Shift (>>)- The right shift operator shifts bits to the right. Each right shift divides the number by 2^n, ignoring the remainder.

Example:
5 >> 1 = 2  
Binary: 0101 >> 1  0010

That's all about the Bitwise Operators that we will use to solve problems using bit manipulation.

Let's understand one last topic of in introduction part, and that is 2's Complement. Many times, learners find it difficult to understand this and their use.

What is 2's Complement?

2’s Complement is a method used by computers to represent negative numbers in binary form. It allows addition, subtraction, and other operations to work seamlessly with both positive and negative integers using the same circuitry.

How to Find 2’s Complement?
To find the 2’s complement of a positive number:
  • Write the number in binary (fixed width, e.g., 8 bits).
  • Invert all the bits (change 0 to 1 and 1 to 0).
  • Add 1 to the result.

With 2’s complement:
  • Positive numbers start from 00000000 (0) to 01111111 (+127)
  • Negative numbers start from 11111111 (–1) to 10000000 (–128)
Example: Find the 2’s Complement of 5
Step 1: Binary of 5 in 8 bits = 00000101
Step 2: Invert bits  11111010
Step 3: Add 1  11111011

Result: 11111011 is -5 in 2s complement form.

Now I hope you have understood all the topics that we have discussed in this post, and are ready to solve real-life problems.

Bit manipulation is a powerful concept that allows you to write faster and more memory-efficient programs. By mastering binary conversions and bitwise operators, you unlock the ability to solve a wide range of DSA problems more effectively.

Stock Span Problem Using Stack.

The stock span problem is a financial problem where we have a series of daily price quotes for a stock and we need to calculate the span of the stock's price for each day. The span of the stock's price for a particular day is defined as the maximum number of consecutive days (including the current day) for which the stock price is less than or equal to the price of the current day.

Example:

Input: [100, 80, 60, 70, 60, 75, 85]

Output: [1, 1, 1, 2, 1, 4, 6]

Explanation:

  • For day 1 (100), the span is 1, as it is the first day.
  • For day 2 (80), the span is 1, as the previous day's price (100) is greater.
  • For day 3 (60), the span is 1, as the previous day's price (80) is greater.
  • For day 4 (70), the span is 2, as the previous day's price (60) is smaller, so we include the day before that (60).
  • For day 5 (60), the span is 1, as the previous day's price (70) is greater.
  • For day 6 (75), the span is 4, as the previous day's price (60) is smaller, so we include the three days before that (60, 70, 60).
  • For day 7 (85), the span is 6, as the previous day's price (75) is smaller, so we include the five days before that (60, 70, 60, 75, 85).


There are many ways to solve this problem, popularly it is solved using stack or dynamic programming and here we are going to discuss all these approaches in detail starting with the brute force approach.

Stock Span Problem Using Brute Force Approach.

In this approach, for each day, we traverse backward and count the number of consecutive days with prices less than or equal to the current day's price. Traverse backward from i-1 to 0 and for each previous day j, compare the stock price at day i with the stock price at day j.

Below is the code implementation of the above approach:
// Cpp program for stock span problem (brute force)
#include <iostream>
#include <vector>
using namespace std;

vector<int> calculateSpan(const vector<int>& prices) {
    int n = prices.size();
    vector<int> span(n, 1);

    for (int i = 0; i < n; ++i) {
        int spanValue = 1;
         
        //traverse backwards and count the number of consecutive days 
        for (int j = i - 1; j >= 0 && prices[j] <= prices[i]; --j) {
            spanValue++;
        }

        span[i] = spanValue;
    }

    return span;
}

int main() {
    vector<int> stockPrices = {100, 80, 60, 70, 60, 75, 85};
    vector<int> span = calculateSpan(stockPrices);

    cout << "Stock Prices: ";
    for (int price : stockPrices) {
         cout << price << " ";
    }

    std::cout << "\nSpans: ";
    for (int s : span) {
        std::cout << s << " ";
    }

    return 0;
}
// Java program for stock span problem - brute force approach
import java.util.Arrays;

public class StockSpan {
    public static void main(String[] args) {
        int[] prices = {100, 80, 60, 70, 60, 75, 85};
        int[] span = calculateSpan(prices);

        System.out.println("Stock Prices: " + Arrays.toString(prices));
        System.out.println("Spans: " + Arrays.toString(span));
    }

    public static int[] calculateSpan(int[] prices) {
        int n = prices.length;
        int[] span = new int[n];
        Arrays.fill(span, 1);

        for (int i = 0; i < n; ++i) {
            int spanValue = 1;
            //traverse backwards and count the number of consecutive days
            for (int j = i - 1; j >= 0 && prices[j] <= prices[i]; --j) {
                spanValue++;
            }

            span[i] = spanValue;
        }

        return span;
    }
}
# Python program to solve stock span problem
def calculate_span(prices):
n = len(prices)
span = [1] * n

for i in range(1, n):
    span_value = 1

    for j in range(i - 1, -1, -1):
        if prices[j] > prices[i]:
            break
        span_value += 1

    span[i] = span_value

return span

stock_prices = [100, 80, 60, 70, 60, 75, 85]
span = calculate_span(stock_prices)

print("Stock Prices: " + str(stock_prices))
print("Spans: " + str(span))
// C# code to solve stock span problem - brute force
using System;

class StockSpan {
    public static void Main() {
        int[] prices = {100, 80, 60, 70, 60, 75, 85};
        int[] span = CalculateSpan(prices);

        Console.WriteLine("Stock Prices: " + string.Join(" ", prices));
        Console.WriteLine("Spans: " + string.Join(" ", span));
    }

    public static int[] CalculateSpan(int[] prices) {
        int n = prices.Length;
        int[] span = new int[n];
        Array.Fill(span, 1);

        for (int i = 0; i < n; ++i) {
            int spanValue = 1;

            for (int j = i - 1; j >= 0 && prices[j] <= prices[i]; --j) {
                spanValue++;
            }

            span[i] = spanValue;
        }

        return span;
    }
}
Output:
Stock Prices: 100 80 60 70 60 75 85 
Spans: 1 1 1 2 1 4 6 

Time Complexity: O(n^2).
Space Complexity: O(1).

Stock Span Problem Using Stack.

In this approach, we utilize a stack to efficiently calculate the span of stock prices. We traverse the array of stock prices once and maintain a stack of previous days' indices along with their corresponding span values. Below are the algorithm steps that you follow for better understanding.

Algorithm Steps:
  • Create an empty stack to store indices.
  • Initialize an array span of the same size as the number of days, initially filled with zeros. This array will store the span for each day.
  • Iterate through each day, starting from the first day.
  • -- While the stack is not empty and the price of the stock on the current day is greater than the price on the day represented by the index at the top of the stack: Pop the index from the stack.
  • -- If the stack is empty, set the span for the current day as the current day itself; otherwise, set it as the difference between the current day and the day represented by the index at the top of the stack.
  • -- Push the current day's index onto the stack.
  • After completing the iteration, the span array contains the span for each day.

Below is the code implementation for the above approach:
// Stock span problem using stack
#include <iostream>
#include <stack>
#include <vector>
using namespace std;

vector<int> calculateSpan(const vector<int>& prices) {
    stack<int> st;
    vector<int> span(prices.size(), 0);

    for (int i = 0; i < prices.size(); ++i) {
        while (!st.empty() && prices[i] >= prices[st.top()]) {
            st.pop();
        }

        span[i] = st.empty() ? i + 1 : i - st.top();
        st.push(i);
    }

    return span;
}

int main() {
    vector<int> prices = {100, 80, 60, 70, 60, 75, 85};
    vector<int> span = calculateSpan(prices);

    cout << "Stock Prices: ";
    for (int price : prices) {
        cout << price << " ";
    }

    cout << "\nStock Spans: ";
    for (int s : span) {
        cout << s << " ";
    }

    return 0;
}
// Stock Span Problem Using Stack
import java.util.Stack;
import java.util.Arrays;

public class StockSpan {
    public static void main(String[] args) {
        int[] prices = {100, 80, 60, 70, 60, 75, 85};
        int[] span = calculateSpan(prices);

        System.out.println("Stock Prices: " + Arrays.toString(prices));
        System.out.println("Stock Spans: " + Arrays.toString(span));
    }

    public static int[] calculateSpan(int[] prices) {
        Stack<Integer> st = new Stack<>();
        int[] span = new int[prices.length];

        for (int i = 0; i < prices.length; i++) {
            while (!st.isEmpty() && prices[i] >= prices[st.peek()]) {
                st.pop();
            }

            span[i] = st.isEmpty() ? i + 1 : i - st.peek();
            st.push(i);
        }

        return span;
    }
}
# Python code for stock span problem using stack
def calculate_span(prices):
stack = []
span = [0] * len(prices)

for i in range(len(prices)):
    while stack and prices[i] >= prices[stack[-1]]:
        stack.pop()

    span[i] = len(stack) if not stack else i - stack[-1]
    stack.append(i)

return span

prices = [100, 80, 60, 70, 60, 75, 85]
span = calculate_span(prices)

print("Stock Prices: " + str(prices))
print("Stock Spans: " + str(span))
// C# code for stock span problem using stack
using System;
using System.Collections.Generic;

public class StockSpan {
    public static void Main(string[] args) {
        int[] prices = {100, 80, 60, 70, 60, 75, 85};
        int[] span = CalculateSpan(prices);

        Console.WriteLine("Stock Prices: " + string.Join(" ", prices));
        Console.WriteLine("Stock Spans: " + string.Join(" ", span));
    }

    public static int[] CalculateSpan(int[] prices) {
        Stack<int> st = new Stack<int>();
        int[] span = new int[prices.Length];

        for (int i = 0; i < prices.Length; i++) {
            while (st.Count > 0 && prices[i] >= prices[st.Peek()]) {
                st.Pop();
            }

            span[i] = st.Count == 0 ? i + 1 : i - st.Peek();
            st.Push(i);
        }

        return span;
    }
}
Output:
Stock Prices: 100 80 60 70 60 75 85 
Spans: 1 1 1 2 1 4 6 

Time Complexity: O(n).
Space Complexity: O(n).

There are many other approaches as well to solve this problem like by using Dynamic Programming and Monitonic Stack that we have covered separately in other articles.

DON'T MISS

Tech News
© all rights reserved
made with by AlgoLesson