Uncommon Words from Two Sentences

🏠 ⬅️ ➡️

A sentence is a string of single-space separated words where each word consists only of lowercase letters.

A word is uncommon if it appears exactly once in one of the sentences, and does not appear in the other sentence.

Given two sentences s1 and s2, return a list of all the uncommon words. You may return the answer in any order.

Example 1:

Input: s1 = "this apple is sweet", s2 = "this apple is sour" Output: ["sweet","sour"]

Example 2:

Input: s1 = "apple apple", s2 = "banana" Output: ["banana"]

Constraints:

  • 1 <= s1.length, s2.length <= 200
  • s1 and s2 consist of lowercase English letters and spaces.
  • s1 and s2 do not have leading or trailing spaces.
  • All the words in s1 and s2 are separated by a single space.

Note: This problem is from LeetCode.
Compiled
Executed
Correct
program main
    implicit none

    character(len=:), allocatable :: s1, s2
    integer :: i, j
    logical :: found

    ! Examples
    call test_example("this apple is sweet", "this apple is sour")
    call test_example("apple apple", "banana")

contains

    subroutine test_example(s1, s2)
        implicit none
        character(len=*), intent(in) :: s1, s2

        write(*,*) 'Testing example: ', trim(s1), ' ', trim(s2)
        call solve(s1, s2)
    end subroutine test_example

    subroutine solve(s1, s2)
        implicit none
        character(len=*), intent(in) :: s1, s2
        character(len=:), allocatable :: words(:)
        integer :: nwords

        ! Split the sentences into words
        call split_into_words(s1, words, nwords)
        call split_into_words(s2, words, nwords)

        ! Find the uncommon words
        do i = 1, nwords
            found = .false.
            do j = 1, nwords
                if (i /= j) then
                    if (words(i) == words(j)) then
                        found = .true.
                        exit
                    end if
                end if
            end do
            if (.not. found) then
                write(*,'(A)') trim(words(i))
            end if
        end do

    end subroutine solve

    subroutine split_into_words(str, words, nwords)
        implicit none
        character(len=*), intent(in) :: str
        character(len=:), allocatable, intent(out) :: words(:)
        integer, intent(out) :: nwords

        integer :: i, pos
        character(len=1) :: c

        nwords = 0
        do i = 1, len_trim(str)
            c = str(i:i)
            if (c == ' ') then
                nwords = nwords + 1
            else
                allocate(character(nwords) :: words(nwords))
                words(nwords) = c
            end if
        end do

    end subroutine split_into_words

end program main
Compiled
Executed
Correct
module uncommon_words

implicit none

contains

subroutine solve(s1, s2, result)

character(len=*), intent(in) :: s1, s2
character(len=:), allocatable, intent(out) :: result

integer :: i, j, k, n
logical :: found
character(len=1) :: c

! Initialize the result
result = ""

! Split the sentences into words
n = 1
do i = 1, len_trim(s1)
    if (s1(i:i) == " ") then
        n = n + 1
    end if
end do
allocate(character(len=n) :: words1(n))
n = 1
do i = 1, len_trim(s2)
    if (s2(i:i) == " ") then
        n = n + 1
    end if
end do
allocate(character(len=n) :: words2(n))

! Store the words in the arrays
k = 1
do i = 1, len_trim(s1)
    if (s1(i:i) /= " ") then
        words1(k) = s1(i:i)
        k = k + 1
    end if
end do
k = 1
do i = 1, len_trim(s2)
    if (s2(i:i) /= " ") then
        words2(k) = s2(i:i)
        k = k + 1
    end if
end do

! Check for uncommon words
do i = 1, size(words1)
    found = .false.
    do j = 1, size(words2)
        if (words1(i) == words2(j)) then
            found = .true.
            exit
        end if
    end do
    if (.not. found) then
        result = trim(result) // " " // words1(i)
    end if
end do

end subroutine solve

end module uncommon_words

program test

use uncommon_words
implicit none

character(len=200) :: s1, s2, result

! Test case 1
s1 = "this apple is sweet"
s2 = "this apple is sour"
call solve(s1, s2, result)
write (*,*) "Result: ", trim(result)

! Test case 2
s1 = "apple apple"
s2 = "banana"
call solve(s1, s2, result)
write (*,*) "Result: ", trim(result)

end program test
🌐 Data from online sources
def k_similarity(s1, s2):
    k = 0
    a, b = list(s1), list(s2)
    for i in range(len(a)):
        if a[i] != b[i]:
            for j in range(i + 1, len(b)):
                if a[i] == b[j] and a[j] != b[j]:
                    a[i], a[j] = a[j], a[i]
                    k += 1
                    break
    return k

The algorithm begins by initializing the counter k to 0. We then create two mutable copies of the inputs: a and b. We loop through each character in a and compare it to its corresponding position in b. If they don't match, we look for matching characters in both b and the later part of a, ensuring that the swap candidate is not 'correct' (i.e., needs to be swapped itself). If we find a good swap candidate, we swap the characters in a and increment the k. We continue this process until reaching the end of the strings, and return k as the final result.

🌐 Data from online sources
int kSimilarity(const std::string& s1, const std::string& s2) {
    int k = 0;
    std::string a = s1, b = s2;
    for (int i = 0; i < a.size(); ++i) {
        if (a[i] != b[i]) {
            for (int j = i + 1; j < b.size(); ++j) {
                if (a[i] == b[j] && a[j] != b[j]) {
                    std::swap(a[i], a[j]);
                    k++;
                    break;
                }
            }
        }
    }
    return k;
}

The algorithm begins by initializing the counter k to 0. We then create two mutable copies of the inputs: a and b. We loop through each character in a and compare it to its corresponding position in b. If they don't match, we look for matching characters in both b and the later part of a, ensuring that the swap candidate is not 'correct' (i.e., needs to be swapped itself). If we find a good swap candidate, we swap the characters in a and increment the k. We continue this process until reaching the end of the strings, and return k as the final result.