Check Strictly Increasing Array by Removing at most One Element in C++.

Given an integer array arr[] of size n, the task is to check if the given array can be made strictly increasing after removing at most one element from the array. Return true if it is possible to make the given array strictly increasing else return falseNote: If the given array is already strictly increasing then simply return true.

  • A strictly increasing array means that for every nums[i] and nums[i + 1], the relationship nums[i] < nums[i + 1] holds.

Example:

Input: arr[] = {1, 2, 12, 5, 7}
Output: true
Explanation: By removing 12 from index 2, the array becomes {1, 2, 5, 7} 
which is strictly increasing.

Input: arr[] = {1, 4, 5, 3, 2}
Output: false
Explanation: By removing any element of the array it is not possible to make 
it strictly increasing.

Input: arr[] = {1, 2, 2, 5, 5}
Output: false

This problem can be solved using multiple approaches and here we are going to understand each of them one by one starting from brute force to optimized one.

Approach 1: Brute Force.

In this approach, we are going to remove each element one by one and then we will check if the resulting array is strictly increasing or not.

Step-by-step explanation:

Step 1: Define a helper function to check if the given array is strictly increasing or not. Return true if the array is strictly increasing, otherwise false.
Step 2: Iterate through the array and simulate removing each element one by one.
Step 3: For each removed element, check if the resulting array is strictly increasing using the helper function.
Step 4: Push the removed element back inside the array if the condition is not satisfied.
Step 5: If any array condition is strictly increasing, we return true, indicating that the array can be made strictly increasing by removing one element.
Step 6: If no such array condition is found even after trying to remove each element, we return false. 

Below is the C++ code implementation of the above approach:

//C++ Brute Force Approach to check strictly increasing array 
#include<iostream>
#include <vector>
using namespace std;

//helper function to check if the array is 
//strictly increasing or not
bool isStrictlyIncreasing(vector<int>& nums) {
    int n = nums.size();
    bool isIncreasing = true;
    
    for (int i = 1; i < n; i++) {
        if (nums[i] <= nums[i - 1]) {
            isIncreasing = false;
            break;
        }
    }

    return isIncreasing;
}

bool canBeIncreasing(vector<int>& nums) {
    int n = nums.size();

    for (int i = 0; i < n; i++) {
        int removedElement = nums[i];
        // Simulate removing the element
        nums.erase(nums.begin() + i); 
        //calling helper function to check
        if (isStrictlyIncreasing(nums)) {
            return true;
        }
        // Put back the removed element
        nums.insert(nums.begin() + i, removedElement); 
    }

    return false;
}

int main(){

    vector<int> nums{1, 2, 12, 5, 7};

    if(canBeIncreasing(nums))
       cout<<"True";
    else
       cout<<"False";   
       
    return 0;
}
Output:
True

Time Complexity: The time complexity of this approach is O(n^2), where n is the number of elements in the array. For each element, we check if the resulting array is strictly increasing, which takes O(n) time. As we do this for each element, the overall time complexity becomes O(n^2).

Space Complexity: The space complexity is O(1) as we use only a constant amount of extra space for variables, and we modify the input array in place without using any additional data structures.


Approach 2: Optimized Approach.

Using the brute force approach we are getting a time complexity of O(n^2) but we can easily optimize the above approach and solve in O(n) time complexity.

Step-by-step explanation:

Step 1: Initialize a variable count to keep track of the number of elements that violate the strictly increasing condition.
Step 2: Iterate through the array from index 1 to the end. If the current element is less than or equal to the previous element, it means it violates the strictly increasing condition.
Step 3: Increment the count and check if it becomes greater than 1. If yes, it means we need to remove more than one element to make the array strictly increasing, so we return false.
Step 4: If the count is 1, it means we found one violating element. We then try removing it and checking if the array becomes strictly increasing.
Step 5: To remove the violating element, we have two choices:
  • If the current element is greater than the element before the previous element (nums[i] > nums[i - 2]), we remove the current element by setting it equal to the previous element.
  • Otherwise, we remove the previous element by setting it equal to the current element.
Step 6: Continue iterating through the array, and if we find any more violating elements, we return false.
Step 7: If we successfully iterate through the entire array without finding any more violating elements, it means we can make the array strictly increasing by removing exactly one element, so we return true.

C++ code implementation of the above approach:

//C++ Optimized Approach to check strictly increasing array 
#include<iostream>
#include <vector>
using namespace std;

//function to check strictly increasing
bool canBeIncreasing(vector<int>& nums) {
    int n = nums.size();
    // Count of violating elements
    int count = 0; 

    for (int i = 1; i < n; i++) {
        if (nums[i] <= nums[i - 1]) {
            count++;
            if (count > 1) {
                return false;
            }

            // Check if removing the current element makes 
            //the array strictly increasing
            if (i == 1 || nums[i] > nums[i - 2]) {
                nums[i - 1] = nums[i];
            } else {
                nums[i] = nums[i - 1];
            }
        }
    }
    return true;
}


int main(){

    vector<int> nums{1, 2, 12, 5, 7};

    if(canBeIncreasing(nums))
       cout<<"True";
    else
       cout<<"False";   

    return 0;
}
Output:
True

Time Complexity: The time complexity of this solution is O(n), where n is the number of elements in the array. We iterate through the array only once.

Space Complexity: The space complexity is O(1) as we use only a constant amount of extra space for variables.

Object Oriented Programming in C++.

Object-Oriented Programming (OOP) is a programming paradigm that organizes and structures code around the concept of "objects," which are self-contained units containing both data and behavior. In OOP, objects represent real-world entities, and the programming revolves around interactions between these objects.


The core principles of Object-Oriented Programming are:

  • Encapsulation.
  • Abstraction.
  • Inheritance.
  • Polymorphism.
We are going to cover all these principles in detail with real-life examples in this post but before understanding them there are a few important terms that we need to understand. 

Class

In C++, a class is a user-defined data type that serves as a blueprint for creating objects. It encapsulates data (attributes) and methods (member functions) that operate on that data. Classes enable developers to model real-world entities, organize code, and implement the principles of Object-Oriented Programming (OOP).

Object

In C++, an object is a concrete instance of a class. It is a self-contained unit that combines data (attributes) and behavior (methods) defined in the class blueprint. Objects represent real-world entities and can interact with each other through their methods and attributes.

Let's take a real-world example to understand the concept of class and object and how it works.

Example: Consider we have a class name Vehicle, the Vehicle class contains attributes like Brand, Model, Color, and Fuel Type. It also has some properties like ChangeGear(), GetFuelLevel(), Accelerate(), and Brake(). Using this Vehicle class as a blueprint, we can create multiple vehicle objects, each with its own unique set of attributes and behavior. 

C++ Example Code:
//C++ Example Code to show working of Class and Objects
#include <iostream>
#include <string>
using namespace std;

class Car {
public:
    // Attributes
    string brand;
    string model;
    string color;
    string fuelType;

    // Methods
    void ChangeGear() {
        cout << "The " << brand << " " << model << " is changing Gear...\n";
    }

    void Accelerate() {
        cout << "The " << brand << " " << model << " is accelerating...\n";
    }

    void Brake() {
        cout << "The " << brand << " " << model << " is braking...\n";
    }
};

int main() {
    // Creating car objects using the Car class
    Car car1;

    car1.brand = "Toyota";
    car1.model = "Camry";
    car1.color = "Blue";
    car1.fuelType = "Petrol";

    car1.ChangeGear();
    car1.Accelerate();
    car1.Brake();

    return 0;
}
Output:
The Toyota Camry is changing Gear...
The Toyota Camry is accelerating...
The Toyota Camry is braking...
The memory required to hold the object's data (attributes) and the code for its methods (member functions) is allocated from the computer's memory.(alert-success)

I hope till now you have understood the two most important terms of OOPs that is class and object. Now we are going to explore the core principles of OOPs one by one.


Encapsulation

Encapsulation is the concept of bundling data and methods within a class, hiding internal implementation details from the outside world. It allows for data abstraction and provides access control through public, private, and protected access specifiers. You can read more about Access Specifiers here.


Example: In the Car class, the attributes (make, model, year) may be declared as private, ensuring that they can only be accessed and modified through public methods like getMake() and setMake(). This way, the internal state of the car object is encapsulated and protected.


Example Code:

#include <iostream>
#include <string>
using namespace std;

class Car {
private:
    string make;
    string model;
    int year;

public:
    // Constructor
    Car(string carMake, string carModel, int carYear) {
        make = carMake;
        model = carModel;
        year = carYear;
    }

    // Getter methods
    string getMake() const {
        return make;
    }
    string getModel() const {
        return model;
    }
    int getYear() const {
        return year;
    }

    // Setter methods
    void setMake(string newMake) {
        make = newMake;
    }
    void setModel(string newModel) {
        model = newModel;
    }
    void setYear(int newYear) {
        year = newYear;
    }
};

int main() {
    // Creating a Car object using the constructor
    Car myCar("Toyota", "Camry", 2022);

    // Using the setter methods to modify attributes
    myCar.setMake("Honda");
    myCar.setModel("Civic");
    myCar.setYear(2021);

    // Displaying the updated car details
    cout << "\nUpdated Car Details:" << endl;
    cout << "Make: " << myCar.getMake() << endl;
    cout << "Model: " << myCar.getModel() << endl;
    cout << "Year: " << myCar.getYear() << endl;

    return 0;
}
Output:
Updated Car Details:
Make: Honda
Model: Civic
Year: 2021

Access specifiers are keywords used in class definitions to control the visibility and accessibility of class members (attributes and methods) from outside the class. (alert-success) 


Abstraction

Abstraction involves representing essential features and behavior of objects while hiding unnecessary details. It allows us to focus on what an object does rather than how it does it.

Abstraction is achieved in C++ through the use of classes and access specifiers (public, private, protected). The public interface of the class represents the abstraction, while the private and protected sections hide the implementation details from external code. 

Example: In a banking application, a BankAccount class may provide methods like deposit(), withdraw(), and getBalance(), abstracting away the complex internal banking operations and exposing only the essential functionality needed by users.


Inheritance

Inheritance is a mechanism that allows a class to inherit properties and behaviors from another class, forming a hierarchical relationship. The derived class (child class) inherits the characteristics of the base class (parent class).
Inheritance allows for code reuse, as the derived class can reuse the properties and behaviors of the base class, eliminating the need to rewrite common code.(alert-success)

They are classified into various types based on the hierarchy and relationships between classes and these are:

  • Single Inheritance: A derived class inherits from only one base class. 
  • Multiple Inheritance: A derived class can inherit from two or more base classes.
  • Multilevel Inheritance: A derived class inherits from another derived class, creating a chain of inheritance.
  • Hierarchical Inheritance: Multiple derived classes inherit from a single base class.
  • Hybrid (or Virtual) Inheritance: A combination of multiple and multilevel inheritance.

Polymorphism

Polymorphism allows objects of different classes to be treated as objects of a common base class. It enables the same method to be implemented in different ways in different classes, based on their specific behavior.

Example: Using the vehicle hierarchy, a generic method like drive() can be defined in the base class Vehicle. Each derived class (Car, Motorcycle, Truck) can provide its own implementation of the drive() method based on the unique way each vehicle type operates.

Fixed Size Sliding Window Algorithm with Example.

The Fixed Size Sliding Window Algorithm is a powerful technique used in computer programming and data processing to efficiently process data in a sliding window fashion. This algorithm is particularly useful when dealing with large data sets or solving problems involving continuous or sequential data processing.


Here in this article, we are going to cover Fixed-Size Sliding Window Algorithm in detail with Example.  


When to use Fixed Size Sliding Window Algorithm? 

The Fixed Size Sliding Window Algorithm is particularly useful in scenarios where you need to efficiently process sequential data by maintaining a fixed-size subset or window of elements. 


Here are some situations where this algorithm can be beneficial:

  • Subarray/Substring Problems: When you need to solve problems that involve finding the maximum or minimum sum, product, or average of a contiguous subarray or substring within a larger array or string.
  • Sequential Data Processing: When you need to process data in a sequential manner, such as time series data, sensor readings, or log files, and perform calculations or computations on a fixed-size subset of the data.
  • Windowed Aggregations: When you need to compute aggregate values (e.g., sum, average, maximum, minimum) over a sliding window of elements in a time-based or sequential data stream.
  • Pattern Matching: When you need to identify or search for specific patterns or sequences within a larger sequence or stream of data.

Algorithm of Fixed Size Sliding Window.

The Fixed Size Sliding Window Algorithm involves maintaining a fixed-size window or subset of elements as it slides through the input data. The window moves one element at a time, allowing for efficient data processing and analysis. 


The algorithm typically follows these steps:


Step 1: Initialize the window with the first 'k' elements from the input data, where 'k' is the desired window size.

Step 2: Process the initial window to perform any required calculations or operations.

Step 3: Slide the window by moving one element forward.

Step 4: Update the window by adding the next element from the input data and removing the last element from the previous window.

Step 5: Perform the necessary computations or operations on the updated window.

Step 6: Repeat steps 3-5 until the end of the input data is reached.


So these are steps that you need to follow to solve any fixed-size sliding window problem, let's understand the algorithm in more detail with one example.


Example of Fixed Size Sliding Window.

Given an array of size n, we need to find the maximum sum of k consecutive elements in the array. 

Example:

Input: num[] = {2, 3, 5, 4, 9, 7, 1}  k = 3
Output: 20

Explanation: 
The sum of all possible subarrays of size 3
{2, 3, 5} = 2+3+5 = 10
{3, 5, 4} = 3+5+4 = 12
{5, 4, 9} = 5+4+9 = 18
{4, 9, 7} = 4+9+7 = 20
{9, 7, 1} = 9+7+1 = 17 
The maximum sum we get by adding the subarray {4, 9, 7} of size 3.

Step by Step Algorithm to solve the above problem using Fixed Size Sliding Window Approach:

Step 1: Start with the given input array nums and the window size k.
Step 2: Initialize variables windowSum and maxSum to 0.
Step 3: Calculate the initial window sum by iterating from index 0 to k-1 and adding each element to windowSum.
Step 4: Assign the value of windowSum to maxSum.
Step 5: Iterate from index k to nums.size() - 1:
  • Add the current element at index i to windowSum.
  • Subtract the element at index i-k (the element that leaves the window) from windowSum.
  • Update maxSum by taking the maximum value between maxSum and windowSum.
Step 6: After the iteration, the value of maxSum will hold the maximum sum of 'k' consecutive elements in the array nums.
Step 7: Return maxSum.

Here is the C++ Code Implementation:
//C++ Program to Find Max Sum of Window Size K
#include <iostream>
#include <vector>
using namespace std;

int maxSumInSlidingWindow(const vector<int>& nums, int k) {
    int windowSum = 0;
    int maxSum = 0;

    // Calculate the initial window sum
    for (int i = 0; i < k; ++i) {
        windowSum += nums[i];
    }

    maxSum = windowSum;

    // Slide the window and update the maximum sum
    for (int i = k; i < nums.size(); ++i) {
        windowSum += nums[i] - nums[i - k];
        maxSum = max(maxSum, windowSum);
    }

    return maxSum;
}

int main() {
    vector<int> nums = {2, 3, 5, 4, 9, 7, 1};
    int k = 3;

    int maxSum = maxSumInSlidingWindow(nums, k);

    cout << "Maximum sum of " << k << " consecutive elements: " << maxSum << endl;

    return 0;
}
Output:
Maximum sum of 3 consecutive elements: 20
  • Time ComplexityThe time complexity of the algorithm is O(N), where N represents the number of elements in the input array nums.
  • Space ComplexityThe space complexity of the algorithm is O(1) since it uses a constant amount of additional space.

The Fixed Size Sliding Window Algorithm offers several advantages, including reduced memory usage, faster processing times, and the ability to solve problems that require analyzing a subset of sequential data.

Zeller's Congruence algorithm | Find the Day for a Date.

Zeller's Congruence algorithm is a mathematical formula that can be used to determine the day of the week for a given date. It was developed by Christian Zeller in the late 19th century and provides a straightforward calculation based on the day, month, and year.


The algorithm takes advantage of a modified calendar where January and February are considered months 13 and 14 of the previous year. This adjustment simplifies the calculation and allows for consistent formulas across all months.


The formula used in Zeller's Congruence algorithm is as follows:

h = (day + (13 * (month + 1)) / 5 + yearOfCentury + yearOfCentury / 4 + century / 4 + 5 * century) % 7

Where:
  • h is the calculated day of the week (0 - Saturday, 1 - Sunday, ..., 6 - Friday).
  • day is the day of the month (1 to 31).
  • month is the month of the year (3 to 14, with January and February adjusted as 13 and 14 respectively).
  • year is the year (e.g., 2023).
  • century is the century part of the year (e.g., 20 for the year 2023).
  • yearOfCentury is the year within the century (e.g., 23 for the year 2023).

The formula calculates a value of h, which represents the day of the week. To map this value to the corresponding day of the week, you can use the following mapping:
  • 0: Saturday
  • 1: Sunday
  • 2: Monday
  • 3: Tuesday
  • 4: Wednesday
  • 5: Thursday
  • 6: Friday

By applying Zeller's Congruence algorithm, you can determine the day of the week for any given date, enabling you to perform various date-related calculations and manipulations in programming.

C++ Program to Find the Day for a Date.

Example code:
//C++ Program Find the Day for a Date
#include <iostream>
using namespace std;

int getDayOfWeek(int day, int month, int year) {
    if (month == 1 || month == 2) {
        month += 12;
        year--;
    }

    int century = year / 100;
    int yearOfCentury = year % 100;

    int h = (day + (13 * (month + 1)) / 5 + yearOfCentury + yearOfCentury / 4 + century / 4 + 5 * century) % 7;

    return h;
}

int main() {
    int day, month, year;

    cout << "Enter the date (DD MM YYYY): ";
    cin >> day >> month >> year;

    int dayOfWeek = getDayOfWeek(day, month, year);

    switch (dayOfWeek) {
        case 0:
            cout << "Saturday\n";
            break;
        case 1:
            cout << "Sunday\n";
            break;
        case 2:
            cout << "Monday\n";
            break;
        case 3:
            cout << "Tuesday\n";
            break;
        case 4:
            cout << "Wednesday\n";
            break;
        case 5:
            cout << "Thursday\n";
            break;
        case 6:
            cout << "Friday\n";
            break;
        default:
            cout << "Invalid day of the week\n";
            break;
    }

    return 0;
}
Output:
Enter the date (DD MM YYYY): 12 06 2023
Monday

C Program to Display Complete Calendar for Given Year.

In this article, we will explore how to write a C program to display a month-by-month calendar for a given year. The program will calculate the number of days in each month and determine the day of the week for the first day of each month. Using this information, it will print a formatted calendar for each month, including the corresponding day of the week for each date.


Steps to Display a month-by-month calendar for a given year:


Step 1: Accept the input year from the user.

Step 2: Define functions to calculate the number of days in a month and the day of the week for the first day of a given month.

Step 3: Iterate through each month of the year and generate the calendar for each month.

Step 4: Format and display the calendar for each month, including the month name and the corresponding day of the week for each date.

Step 5: Repeat the above steps for all twelve months of the year.


Code Example:

//C Program to print month by month calendar for given year
#include <stdio.h>

//function to check leap year
int isLeapYear(int year) {
    if (year % 400 == 0)
        return 1;
    if (year % 100 == 0)
        return 0;
    if (year % 4 == 0)
        return 1;
    return 0;
}

//function to get the number of day in that month
int getNumberOfDays(int month, int year) {
    int daysInMonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

    if (month == 2 && isLeapYear(year))
        return 29;
    else
        return daysInMonth[month - 1];
}

//
int getDayOfWeek(int day, int month, int year) {
    int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
    if (month < 3)
        year--;

    int dayOfWeek = (year + year / 4 - year / 100 + year / 400 + t[month - 1] + day) % 7;

    return dayOfWeek;
}

void displayCalendar(int year) {
    char *months[] = {"January", "February", "March", "April", "May", "June",
                      "July", "August", "September", "October", "November", "December"};

    for (int month = 1; month <= 12; month++) {
        int days = getNumberOfDays(month, year);
        int firstDayOfWeek = getDayOfWeek(1, month, year);

        printf("\n--------------- %s ---------------\n", months[month - 1]);
        printf("Sun Mon Tue Wed Thu Fri Sat\n");

        int day;
        for (int space = 0; space < firstDayOfWeek; space++)
            printf("    ");
        for (day = 1; day <= days; day++) {
            printf("%3d ", day);
            if ((day + firstDayOfWeek) % 7 == 0)
                printf("\n");
        }
        if ((day + firstDayOfWeek) % 7 != 0)
            printf("\n");
    }
}

int main() {
    int year;

    printf("Enter the year: ");
    scanf("%d", &year);

    displayCalendar(year);

    return 0;
}
Output:
Enter the year: 2023
--------------- January ---------------
Sun Mon Tue Wed Thu Fri Sat
  1   2   3   4   5   6   7 
  8   9  10  11  12  13  14 
 15  16  17  18  19  20  21 
 22  23  24  25  26  27  28 
 29  30  31 

--------------- February ---------------
Sun Mon Tue Wed Thu Fri Sat
              1   2   3   4 
  5   6   7   8   9  10  11 
 12  13  14  15  16  17  18 
 19  20  21  22  23  24  25 
 26  27  28 

--------------- March ---------------
Sun Mon Tue Wed Thu Fri Sat
              1   2   3   4 
  5   6   7   8   9  10  11 
 12  13  14  15  16  17  18 
 19  20  21  22  23  24  25 
 26  27  28  29  30  31 
--------------- April ---------------
Sun Mon Tue Wed Thu Fri Sat
                          1 
  2   3   4   5   6   7   8 
  9  10  11  12  13  14  15 
 16  17  18  19  20  21  22 
 23  24  25  26  27  28  29 
 30 

--------------- May ---------------
Sun Mon Tue Wed Thu Fri Sat
      1   2   3   4   5   6 
  7   8   9  10  11  12  13 
 14  15  16  17  18  19  20 
 21  22  23  24  25  26  27 
 28  29  30  31 

--------------- June ---------------
Sun Mon Tue Wed Thu Fri Sat
                  1   2   3 
  4   5   6   7   8   9  10 
 11  12  13  14  15  16  17 
 18  19  20  21  22  23  24 
 25  26  27  28  29  30 
--------------- July ---------------
Sun Mon Tue Wed Thu Fri Sat
                          1 
  2   3   4   5   6   7   8 
  9  10  11  12  13  14  15 
 16  17  18  19  20  21  22 
 23  24  25  26  27  28  29 
 30  31 

--------------- August ---------------
Sun Mon Tue Wed Thu Fri Sat
          1   2   3   4   5 
  6   7   8   9  10  11  12 
 13  14  15  16  17  18  19 
 20  21  22  23  24  25  26 
 27  28  29  30  31 

--------------- September ---------------
Sun Mon Tue Wed Thu Fri Sat
                      1   2 
  3   4   5   6   7   8   9 
 10  11  12  13  14  15  16 
 17  18  19  20  21  22  23 
 24  25  26  27  28  29  30 


--------------- October ---------------
Sun Mon Tue Wed Thu Fri Sat
  1   2   3   4   5   6   7 
  8   9  10  11  12  13  14 
 15  16  17  18  19  20  21 
 22  23  24  25  26  27  28 
 29  30  31 

--------------- November ---------------
Sun Mon Tue Wed Thu Fri Sat
              1   2   3   4 
  5   6   7   8   9  10  11 
 12  13  14  15  16  17  18 
 19  20  21  22  23  24  25 
 26  27  28  29  30 

--------------- December ---------------
Sun Mon Tue Wed Thu Fri Sat
                      1   2 
  3   4   5   6   7   8   9 
 10  11  12  13  14  15  16 
 17  18  19  20  21  22  23 
 24  25  26  27  28  29  30 
 31 

  • Time Complexity: The time complexity of the code can be considered as O(1) since the majority of the operations involve constant time complexity.
  • Space Complexity: The space complexity of the code is constant or O(1).

DON'T MISS

Nature, Health, Fitness
© all rights reserved
made with by AlgoLesson